首先感谢动力节点和老师的教学分享!Respect!

学习视频来源:
B站:
https://www.bilibili.com/video/BV1oP4y1K7QT/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=07c8a1a7d89af39fe20c3a6894f5ff6a

文件资源:
主流框架 链接:https://pan.baidu.com/s/10HGe7wP1aed2HUCihc3-yQ?pwd=afjd 提取码:afjd

SpringMVC5 学习笔记

文章目录

  • 首先感谢动力节点和老师的教学分享!Respect!
  • SpringMVC5 学习笔记
    • 一、SpringMVC概述
      • 1. 什么是SpringMVC
      • 2. SpringMVC框架的优点
      • 3. 基于注解的SpringMVC框架开发的步骤
    • 二、SpringMVC注解式开发
      • 1. 分析web请求
      • 2. @RequestMapping注解详解
        • 2.1 指定模块名称
        • 2.2 对请求提交方式的定义
      • 3. 五种数据提交方式的优化
      • 4. 中文乱码解决方案
      • 5. action方法的返回值
      • 6. 完成ajax请求访问服务器,返回学生集合
      • 7. 四种跳转方式
      • 8. SpringMVC默认的参数类型
      • 9.日期处理
      • 10. 资源在WEB-INF目录下
    • 三、SpringMVC的拦截器
      • 1. 拦截器执行的时机
      • 2. 拦截器实现的两种方式
      • 3. 拦截器实现的步骤
    • 四、SSM整合的步骤

一、SpringMVC概述

1. 什么是SpringMVC

它是基于MVC开发模式的框架,用来优化控制器。它是Spring家族的一员。它也具备IOC和AOP。

  • 什么是MVC?

    • 它是一种开发模式,它是模型视图控制器的简称。所有的web应用都是基于MVC开发。
    • M:模型层,包含实体类,业务逻辑层,数据访问层
    • V:视图层,html,javaScript,vue等都是视图层,用来显现数据
    • C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件

2. SpringMVC框架的优点

  1. 轻量级,基于MVC的框架

  2. 易于上手,容易理解,功能强大

  3. 它具备IOC和AOP

    • 方便整合Strtus,MyBatis,Hiberate,JPA 等其他框架。
  4. 完全基于注解开发

    • 在Controller, Service, Dao 都可以使用注解。方便灵活。
    • 使用@Controller 创建处理器对象,
    • @Service 创建业务对象,
    • @Autowired 或者@Resource 在控制器类中注入 Service,在Service 类中注入 Dao。
  5. SpringMVC优化的方向

  6. SpringMVC执行的流程

    执行流程说明:

    1. 向服务器发送HTTP请求,请求被前端控制器 DispatcherServlet 捕获。

    2. DispatcherServlet 根据<servlet-name>中的配置对请求的URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用 HandlerMapping 获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回。

    3. DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter。

    4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

      • HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。

      • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。

      • 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。

      • 数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。

    5. Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。

    6. 根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet。

    7. ViewResolver 结合Model和View,来渲染视图。

    8. 视图负责将渲染结果返回给客户端

3. 基于注解的SpringMVC框架开发的步骤

  1. 新建项目,选择webapp模板。

  2. 修改目录,添加缺失的test,java,resources(两套),并修改目录属性

  3. 修改pom.xml文件,添加SpringMVC的依赖,添加Servlet的依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.shanglinsong</groupId><artifactId>springmvc_001_demo</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>springmvc_001_demo Maven Webapp</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!-- SpringMVC依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version></dependency><!-- Servlet依赖 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><build><finalName>springmvc_001_demo</finalName><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes></resource><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes></resource></resources></build>
    </project>
    
  4. 在/main/resources目录下利用XML的Spring模板添加springmvc.xml配置文件,指定包扫描,添加视图解析器。该文件名可以任意命名。推荐使用springmvc.xml。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!--添加包扫描--><context:component-scan base-package="com.shanglinsong.springmvc.controller"></context:component-scan><!--添加视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--配置前缀--><property name="prefix" value="/admin/"></property><!--配置后缀--><property name="suffix" value=".jsp"></property></bean>
    </beans>
    
    • SpringMVC框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器

      InternalResouceViewResolver 中引入了请求的前辍与后辍。而action中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。

    • <context:component-scan>: 用来进行包扫描,这里用于指定@Controller注解所在的包路径。

  5. 删除web.xml文件,新建web.xml(若版本无问题则不需要删除,删除原生web.xml文件的主要目的是为了防止版本过老无法支持框架运行)

  6. 在web.xml文件中注册springMVC框架(所有的web请求都是基于servlet的)

    • 因为web的请求都是由Servlet来进行处理的,而SpringMVC的核心处理器就是一个DispatcherServlet,它负责接收客户端的请求,并根据请求的路径分派给对应的action(控制器)进行处理,处理结束后依然由核心处理器DispatcherServlet进行响应返回。
    • 中央调度器的全限定性类名在导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包org.springframework.web.servlet下可找到。
    <!--注册SpringMVC框架-->
    <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param>
    </servlet>
    <servlet-mapping><servlet-name>springmvc</servlet-name><!--指定拦截什么样的请求http://localhost:8080/onehttp://localhost:8080/index.jsphttp://localhost:8080/demo.action<a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>--><url-pattern>*.action</url-pattern>
    </servlet-mapping>
    
    • <param-value>classpath:springmvc.xml</param-value>表示从类路径下加载SpringMVC的配置文件。
    • <url-pattern>指定拦截以.action结尾的请求,交给核心处理器DispatcherServlet处理。
  7. 在webapp目录下新建admin目录,在admin目录下新建main.jsp页面,删除index.jsp页面,并新建,发送请求给服务器

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/22Time: 18:31To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>springmvc_001_demo</title>
    </head>
    <body><a href="${pageContext.request.contextPath}/sls/hello.action">访问action</a>
    </body>
    </html>
    
  8. 在webapp目录上新添目录/admin。在/admin目录下新建main.jsp页面。用来进行服务器处理完毕后数据的回显。

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/22Time: 18:34To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>main</title>
    </head>
    <body>
    <h2>main.......</h2>
    </body>
    </html>
  9. 开发HelloSpringMvc.java -->控制器(相当于以前的servlet)。这是一个普通的类,不用继承和实现接口。类中的每个方法就是一个具体的action控制器。

    package com.shanglinsong.springmvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.HelloSpringMVC* @date 2023/1/22* @since 1.0*/
    @Controller //交给Spring去创建对象
    @RequestMapping("/sls")
    public class HelloSpringMVC {/*** 以前的Servlet的规范* protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}* action中所有的功能实现都是由方法来完成的* action方法的规范* 1)访问权限是public* 2)方法的返回值任意,以返回String居多。* 3)方法名称任意* 4)方法可以没有参数,如果有可是任意类型,用来接收客户端提交上来的数据。* 5)要使用@RequestMapping注解来声明一个访问的路径(名称)**/@RequestMapping("/hello")public String one(){System.out.println("服务器被访问到啦!");return "main"; //可以直接跳到/admin/main.jsp页面上}
    }
    
    • @Controller:表示当前类为处理器,交给Spring容器去创建对象。
    • @RequestMapping:表示路径映射。该注解可以加在类上相当于包名,还可以加在方法上相当于action的名称,都是来指定映射路径的。
      • 其中:

        • /sls 是类上的注解路径
        • /hello 是方法上的注解路径
  10. 添加tomcat进行测试功能

二、SpringMVC注解式开发

1. 分析web请求

  • web请求执行的流程
    核心处理器
    index.jsp<--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法
    one.jsp <---------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法

  • DispatcherServlet要在web.xml文件中注册才可用。

2. @RequestMapping注解详解

2.1 指定模块名称

  • 通过@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方法上,也可以注解在类上,但意义是不同的。value 属性值常以“/”开始。@RequestMapping 的 value 属性用于定义所匹配请求的 URI。

  • 一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI部分可以被抽取到注解在类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块(相当于包)的名称。URI 的请求是相对于 Web 的根目录。换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定义的模块名称。

  • 此注解就是来映射服务器访问的路径。

  1. 此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)

    @RequestMapping("/demo")
    public String demo(){System.out.println("服务器被访问到了.......");return "main";  //可以直接跳到/admin/main.jsp页面上
    }
    
    <a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
    
  2. 此注解可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的action的名称

    @RequestMapping("/user")
    public class DemoAction1 {..}
    
    <a href="${pageContext.request.contextPath}/user/demo.action">访问服务器</a>
    

2.2 对请求提交方式的定义

  • 对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交

  • 方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GETRequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交。

  • 此注解可区分get请求和post请求

@Controller
public class ReqAction {@RequestMapping(value = "/req",method = RequestMethod.GET)public String req(){System.out.println("我是处理get请求的........");return "main";}@RequestMapping(value = "/req" ,method = RequestMethod.POST)public String req1(){System.out.println("我是处理post请求的........");return "main";}
}
  • 客户端浏览器常用的请求方式,及其提交方式有以下几种:

    • 也就是说,只要指定了处理器方法匹配的请求提交方式为 POST,则相当于指定了请求发送的方式:要么使用表单请求,要么使用 AJAX 请求。其它请求方式被禁用。
    • 当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求。
  • 一一对应 举例:

    • GET请求:

      jsp:

      <form action="${pageContext.request.contextPath}/sls/hello1.action" method="get"><input type="submit" value="get提交">
      </form>
      

      action:

      @RequestMapping(value = "/hello1", method = RequestMethod.GET)
      public String reqGet(){System.out.println("服务器被访问到啦,访问提交形式为GET!");return "main";
      }
      

      请求结果:

    • POST请求:

      jsp:

      <form action="${pageContext.request.contextPath}/sls/hello1.action" method="post"><input type="submit" value="post提交">
      </form>
      

      action:

      @RequestMapping(value = "/hello1", method = RequestMethod.POST)
      public String reqPost(){System.out.println("服务器被访问到啦,访问提交形式为POST!");return "main";
      }
      

      请求结果:

3. 五种数据提交方式的优化

  • 前四种数据注入的方式,会自动进行类型转换。但无法自动转换日期类型。
  1. 单个提交数据

    在方法中声明一个和表单提交的参数名称相同的参数,由框架按照名称直接注入。

    • 页面:
    <form action="${pageContext.request.contextPath}/one.action">姓名:<input name="myname"><br>年龄:<input name="age"><br><input type="submit" value="提交">
    </form>
    
    • action:
    @RequestMapping("/one")
    public String one(String myname,int age){  // ===>自动注入,并且类型转换System.out.println("myname="+myname+",age="+(age+100));return "main";
    }
    
  2. 对象封装提交数据

    在方法中声明一个自定义的实体类参数,框架调用实体类中相应的setter方法注入属性值,只要保证实体类中成员变量的名称与提交请求的name属性值一致即可。

    在提交请求中,保证请求参数的名称与实体类中成员变量的名称一致,则可以自动创建对象,则可以自动提交数据,自动类型转换,自动封装数据到对象中。

    • 实体类:
    public class Users {private String name;private int age;getter and setterconstructortoString
    }
    
    • 页面:
    <form action="${pageContext.request.contextPath}/two.action" method="post">姓名:<input name="name"><br>年龄:<input name="age"><br><input type="submit" value="提交">
    </form>
    
    • action:
    @RequestMapping("/two")
    public String two(Users u){System.out.println(u);return "main";
    }
    
  3. 动态占位符提交

    使用框架提供的一个注解@PathVariable,将请求url中的值作为参数进行提取,只能是超链接。restful风格下的数据提取方式。restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    仅限于超链接或地址拦提交数据。它是一杠一值,一杠一大括号,使用注解@PathVariable来解析。

    • 页面:
    <a href="${pageContext.request.contextPath}/three/张三/22.action">动态提交</a>
    
    • action:
    @RequestMapping("/three/{uname}/{uage}")
    public String three(@PathVariable("uname")  // ===>用来解析路径中的请求参数String name,@PathVariable("uage")int age){System.out.println("name="+name+",age="+(age+100));return "main";
    }
    
  4. 映射名称不一致

    提交请求参数与action方法的形参的名称不一致,使用注解@RequestParam来解析

    • 页面:
    <form action="${pageContext.request.contextPath}/sls/four.action" method="get">姓名:<input name="name"><br>年龄:<input name="age"><br><input type="submit" value="提交">
    </form>
    
    • action:
    @RequestMapping("/four")
    public String four(@RequestParam("name")  // ===>专门用来解决名称不一致的问题String uname,@RequestParam("age")int uage){System.out.println("uname="+uname+",uage="+(uage+100));return "main";
    }
    
  5. 手工提取数据

    在方法参数中声明一个request对象,使用request的getParameter()获取表单提交的数据,这样得到的数据还要手工进行数据类型的转换。

    • 页面:
    <form action="${pageContext.request.contextPath}/sls/five.action" method="post">姓名:<input name="name"><br>年龄:<input name="age"><br><input type="submit" value="提交">
    </form>
    
    • action:
    @RequestMapping("/five")
    public String five(HttpServletRequest request){String name = request.getParameter("name");int age = Integer.parseInt(request.getParameter("age"));System.out.println("name="+name+",age="+(age+100));return "main";
    }
    

4. 中文乱码解决方案

  • 在web.xml文件中配置过滤器。

    <filter><filter-name>encode</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!--配置参数private String encoding;private boolean forceRequestEncoding;private boolean forceResponseEncoding;--><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param>
    </filter>
    <filter-mapping><filter-name>encode</filter-name><url-pattern>/*</url-pattern>
    </filter-mapping>
    

5. action方法的返回值

  1. String:

    • 客户端资源的地址,自动拼接前缀和后缀。还可以屏蔽自动拼接字符串,可以指定返回的路径。
    • 处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。

  2. Object:

    • 返回json格式的对象。自动将对象或集合转为json。使用的jackson工具进行转换,必须要添加jackson依赖。一般用于ajax请求。
    • 处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
    • Ajax请求多用于Object返回值类型。由于转换器底层使用了Jackson 转换方式将对象转换为JSON 数据,所以需要添加Jackson的相关依赖。
  3. void:

    • 无返回值,一般用于ajax请求。
    • 对于处理器方法返回 void 的应用场景,应用在AJAX 响应处理。若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。我们SSM整合案例中的分页使用的就是无返回值。
  4. 基本数据类型,用于ajax请求。

  5. ModelAndView:

    • 若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
    • 在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。
    • 较少使用。

6. 完成ajax请求访问服务器,返回学生集合

  1. 添加jackson依赖

    <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version>
    </dependency>
    
  2. 在webapp目录下新建js目录,添加jQuery函数库

  3. 在index.jsp页面上导入函数库

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/28Time: 16:48To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html><head><title>AjaxDemo</title></head><body><script src="js/jquery-3.3.1.js"></script><script>/*function show(){$.ajax({url: "${pageContext.request.contextPath}/ajax.action",type: "get",dataType: "json",success: function(stu){$("#oneStu").html(stu.name + "----" + stu.age);}})}*/function show() {$.ajax({url:"${pageContext.request.contextPath}/ajax.action",dataType:"json",type:"get",success:function (list) {//  alert(list);var s="";$.each(list,function (i,stu) {//  alert(stu);s+=stu.name+"----"+stu.age+"<br>";});$("#mydiv").html(s);}});}</script><a href="javascript:show()">ajax访问服务器,返回一个学生</a><br><%--<div id="oneStu"></div>--%><div id="mydiv"></div></body>
    </html>
    
  4. 在action上添加注解@ResponseBody,用来处理ajax请求

    package com.shanglinsong.springmvc.controller;import com.shanglinsong.springmvc.pojo.Student;
    import jdk.nashorn.internal.objects.annotations.Constructor;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;import java.util.ArrayList;
    import java.util.List;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.AjaxDemo* @date 2023/1/28* @since 1.0*/
    @Controller
    public class AjaxDemo {/*@RequestMapping("/ajax")@ResponseBodypublic Object ajax(){System.out.println("接收到了请求");Student stu = new Student("张三", 22);return stu;}*///处理ajax请求,一定要加@ResponseBody@ResponseBody@RequestMapping("/ajax")public List<Student> ajax(){Student stu1 = new Student("张三",22);Student stu2 = new Student("李四",24);Student stu3 = new Student("王五",23);List<Student> list = new ArrayList<>();list.add(stu1);list.add(stu2);list.add(stu3);//调用json转换工具ObjectMapper进行转换return list;  //===>springmvc负责转换成json}
    }
    
  5. 在springmvc.xml文件中添加注解驱动<mvc:annotationdriven/>,它用来解析@ResponseBody注解

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><context:component-scan base-package="com.shanglinsong.springmvc.controller"></context:component-scan><mvc:annotation-driven></mvc:annotation-driven>
    </beans>
    
  • 测试结果:

    • 网页端:

    • 直接访问ajax.action,返回值为json格式数据

7. 四种跳转方式

  • 默认的跳转是请求转发,直接跳转到jsp页面展示,

    • 还可以使用框架提供的关键字redirect:,进行一个重定向操作,包括重定向页面和重定向action,
    • 使用框架提供的关键字forward:,进行服务器内部转发操作,包括转发页面和转发action。
    • 当使用redirect:和forward:关键字时,视图解析器中前缀后缀的拼接就无效了。
  • 本质还是两种跳转:请求转发和重定向,衍生出四种是:

    1. 请求转发页面
    @RequestMapping("/one")
    public String one(){System.out.println("这是请求转发页面跳转.........");return "main";  //默认是请求转发,使用视图解析器拼接前缀后缀进行页面跳转
    }
    
    1. 转发action
    @RequestMapping("/two")
    public String two(){System.out.println("这是请求转发action跳转.........");//  /admin/  /other.action  .jsp//forward: 这组字符串可以屏蔽前缀和后缀的拼接.实现请求转发跳转return "forward:/other.action";  //默认是请求转发,使用视图解析器拼接前缀后缀进行页面跳转
    }
    
    1. 重定向页面
    @RequestMapping("/three")
    public String three(){System.out.println("这是重定向页面.......");//redirect:  这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转return "redirect:/admin/main.jsp";
    }
    
    1. 重定向action
    @RequestMapping("/four")
    public String four(){System.out.println("这是重定向action.......");//redirect:  这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转return "redirect:/other.action";
    }
    
    • 随便跳
    @RequestMapping("/five")
    public String five(){System.out.println("这是随便跳.......");return "forward:/fore/login.jsp";
    }
    
  • 测试

    • jsp

      <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/28Time: 19:06To change this template use File | Settings | File Templates.
      --%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head><title>forward and redirect</title>
      </head>
      <body><a href="${pageContext.request.contextPath}/one.action">请求转发页面(默认)</a><br><a href="${pageContext.request.contextPath}/two.action">请求转发action</a><br><a href="${pageContext.request.contextPath}/three.action">重定向页面</a><br><a href="${pageContext.request.contextPath}/four.action">重定向action</a><br>
      </body>
      </html>
      
    • JumpAction

      package com.shanglinsong.springmvc.controller;import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.JumpAction* @date 2023/1/28* @since 1.0*/
      @Controller
      public class JumpAction {@RequestMapping("/one")public String one() {System.out.println("请求转发页面(默认)");//以前的访问方式//request.getRequestDispatcher("/admin/main.jsp").forward(request,response);//观察地址栏的变化:  http://localhost:8080/one.action//return "main"; //默认的访问方式是自动拼接前缀和后缀进行跳转return "forward:/admin/main.jsp";//只要使用了forward:就可以屏蔽前缀和后缀的拼接,自己手工构建返回的全部路径+.jsp}@RequestMapping("/two")public String two(){System.out.println("请求转发action");//观察地址栏的变化:  http://localhost:8080/two.actionreturn "forward:/other.action";   //不使用forward:,就会是这样的路径  /admin/other.action/.jsp}@RequestMapping("/three")public String three(){System.out.println("重定向页面");//观察地址栏的变化  http://localhost:8080/admin/main.jspreturn "redirect:/admin/main.jsp";//只要使用了redirect:就可以屏蔽前缀和后缀的拼接}@RequestMapping("/four")public String four(){System.out.println("重定向action");//观察地址栏的变化  http://localhost:8080/other.actionreturn "redirect:/other.action";//只要使用了redirect:就可以屏蔽前缀和后缀的拼接}
      }
      
    • OtherAction

      package com.shanglinsong.springmvc.controller;import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.OtherAction* @date 2023/1/28* @since 1.0*/
      @Controller
      public class OtherAction {@RequestMapping("/other")public String other(){return "other";}
      }
      

8. SpringMVC默认的参数类型

  • 不需要去创建,直接拿来使用即可。

    1. HttpServletRequest
    2. HttpServletResponse
    3. HttpSession
    4. Model
    5. Map
    6. ModelMap
  • 做一个数据,传到main.jsp页面上

    Users u = new Users("张三",22);
    //传递数据
    request.setAttribute("requestUsers",u);
    session.setAttribute("sessionUsers",u);
    model.addAttribute("modelUsers",u);
    map.put("mapUsers",u);
    modelMap.addAttribute("modelMapUsers",u);
    
    • 注意:Map,Model,ModelMap和request一样,都使用请求作用域进行数据传递。所以服务器端的跳转必须是请求转发。
  • 测试

    • jsp

      <a href="${pageContext.request.contextPath}/param.action">测试默认参数类型</a>
      
    • ParamAction

      package com.shanglinsong.springmvc.controller;import com.shanglinsong.springmvc.pojo.Student;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      import java.util.Map;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.ParamAction* @date 2023/1/28* @since 1.0*/
      @Controller
      public class ParamAction {@RequestMapping("/param")public String param(HttpServletRequest request,HttpServletResponse response,HttpSession session,Model model,ModelMap modelMap,Map map){// Map, Model, ModelMap, request 都使用请求作用域进行传值,// 所以必须使用请求转发方式进行跳转,否则丢失数据Student stu = new Student("张三", 22);request.setAttribute("requestStu", stu);session.setAttribute("sessionStu", stu);modelMap.addAttribute("modelMapStu", stu);model.addAttribute("modelStu", stu);map.put("mapStu", stu);// 切记请求转发,使用redirect重定向会丢失数据return "main";}
      }
      
    • main.jsp

      <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/28Time: 19:11To change this template use File | Settings | File Templates.
      --%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head><title>Main</title>
      </head>
      <body>
      <h2>Main........</h2>
      <p>requestStudent: ${requestStu}</p>
      <p>sessionStudent: ${sessionStu}</p>
      <p>modelMapStudent: ${modelMapStu}</p>
      <p>modelStudent: ${modelStu}</p>
      <p>mapStudent: ${mapStu}</p>
      </body>
      </html>
      
    • 页面呈现

9.日期处理

  1. 日期的提交处理

    • jsp

      <form action="${pageContext.request.contextPath}/mydate.action">日期:<input type="date" name="mydate"><br><input type="submit" value="提交">
      </form>
      
    1. 单个日期处理

      要使用注解@DateTimeFormat,此注解必须搭配springmvc.xml文件中的<mvc:annotationdriven标签>

      @RequestMapping("/mydate")
      public String submitDate(HttpServletRequest request,@DateTimeFormat(pattern = "yyyy-MM-dd")Date mydate){System.out.println(mydate);System.out.println(sdf.format(mydate));request.setAttribute("mydate", sdf.format(mydate));return "show";
      }
      
    2. 类中全局日期处理

      注册一个注解,用来解析本类中所有的日期类型,自动转换。

      @InitBinder
      public void initBinder(WebDataBinder dataBinder){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
      }@RequestMapping("/mydate")
      public String submitDate(HttpServletRequest request,// @DateTimeFormat(pattern = "yyyy-MM-dd")Date mydate){System.out.println(mydate);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");System.out.println(sdf.format(mydate));request.setAttribute("mydate", sdf.format(mydate));return "show";
      }
      
    3. 在类的成员setXXX()方法上使用@DateTimeFormat注解

      @DateTimeFormat(pattern = "yyyy-MM-dd")
      public void setBirthday(Date birthday) {this.birthday = birthday;
      }
      

      但这种解决方案要在每个使用日期类型的地方都去添加使用@DateTimeFormat注解,比较麻烦,我们可以使用@InitBinder注解来进行类中统一日期类型的处理。

  2. 日期的显示处理

    在页面上显示好看的日期,必须使用JSTL。

    步骤:

    1. 添加依赖jstl
    <dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version>
    </dependency>
    
    1. 在页面上导入标签库

      • 如果是单个日期对象,直接转为好看的格式化的字符串进行显示.

      • 如果是list中的实体类对象的成员变量是日期类型,则必须使用jstl进行显示.

    <%--导入jstl核心标签库--%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--导入jstl格式化标签库--%>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    
    1. 使用标签显示数据
    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 10:14To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%--导入jstl核心标签库--%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--导入jstl格式化标签库--%>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <html>
    <head><title>show</title>
    </head>
    <body>
    <h3>mydate: ${mydate}</h3><table width="800px" border="1"><tr><th>姓名</th><th>年龄</th><th>生日</th></tr><c:forEach items="${list}" var="stu"><tr><td>${stu.name}</td><td>${stu.age}</td><td>${stu.birthday}------ <fmt:formatDate value="${stu.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate></td></tr></c:forEach>
    </table>
    </body>
    </html>
    
    • action

      @RequestMapping("/list")
      public String list(HttpServletRequest request) throws ParseException {Student stu1 = new Student("张三", 22,sdf.parse("2000-01-01"));Student stu2 = new Student("李四", 33, sdf.parse("2001-08-11"));Student stu3 = new Student("王五", 44, sdf.parse("2002-09-21"));List<Student> list = new ArrayList<>();list.add(stu1);list.add(stu2);list.add(stu3);request.setAttribute("list",list);return "show";
      }
      
    • 测试结果

10. 资源在WEB-INF目录下

  • 此目录下的动态资源,不可直接访问,只能通过请求转发的方式进行访问 。

  • 很多企业会将动态资源放在WEB-INF目录下,这样可以保证资源的安全性。在WEB-INF目录下的动态资源不可以直接访问,必须要通过请求转发的方式进行访问。这样避免了通过地址栏直接对资源的访问。

  • 重定向也无法访问动态资源。

  • 目录结构

  • 默认index.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 10:47To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>index</title>
    </head>
    <body>
    <h1>登录</h1>
    <form action="${pageContext.request.contextPath}/login.action">姓名:<input type="text" name="name"><br>密码:<input type="password" name="password"><br><input type="submit" value="提交">
    </form>
    </body>
    </html>
    
  • jsp/index.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 10:56To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>index</title>
    </head>
    <body>
    <h2>index......</h2>
    </body>
    </html>
    
  • jsp/login.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 10:57To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>login</title>
    </head>
    <body>
    <h2>login......</h2>
    <h2>${msg}</h2>
    </body>
    </html>
    
  • jsp/main.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 10:58To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>main</title>
    </head>
    <body>
    <h2>main......</h2>
    </body>
    </html>
    
  • ShowAction

    package com.shanglinsong.springmvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.HttpRequestHandler;
    import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.ShowAction* @date 2023/1/29* @since 1.0*/
    @Controller
    public class ShowAction {@RequestMapping("/showIndex")public String showIndex(){System.out.println("访问到了index页面!");return "index";}@RequestMapping("/showLogin")public String showLogin(){System.out.println("访问到了login页面!");return "login";}@RequestMapping("/showMain")public String showMain(){System.out.println("访问到了main页面!");return "main";}@RequestMapping("/login")public String login(String name, String password,HttpServletRequest request){if("admin".equals(name) && "123".equals(password)){return "main";}request.setAttribute("msg", "用户名或密码不正确!");return "login";}
    }
    
  • 如此配置,网页将无法直接通过url对jsp文件进行访问,只能通过请求转发方式进行访问。

三、SpringMVC的拦截器

  • 针对请求和响应进行的额外的处理。在请求和响应的过程中添加预处理,后处理和最终处理。

  • SpringMVC 中的 Interceptor 拦截器,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。

  • 拦截器的应用场景

    • 日志记录:记录请求信息的日志
    • 权限检查,如登录检查
    • 性能检测:检测方法的执行时间
  • 拦截器的执行原理

1. 拦截器执行的时机

  1. preHandle():

    在请求被处理之前进行操作,预处理

    • 该方法在处理器方法执行之前执行。
    • 其返回值为 boolean,若为 true,则紧接着会执行处理器方法,且会将 afterCompletion()方法放入到一个专门的方法栈中等待执行。
  2. postHandle():

    在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果,后处理

    • 该方法在处理器方法执行之后执行。
    • 处理器方法若最终未被执行,则该方法不会执行。
    • 由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。
  3. afterCompletion():

    所有的请求响应结束后执行善后工作,清理对象,关闭资源 ,最终处理。

    • 当preHandle()方法返回 true 时,会将该方法放到专门的方法栈中,等到对请求进行响应的所有工作完成之后才执行该方法。即该方法是在中央调度器渲染(数据填充)了响应页面之后执行的,此时对 ModelAndView 再操作也对响应无济于事。
    • afterCompletion 最后执行的方法,清除资源,例如在 Controller 方法中加入数据等。

2. 拦截器实现的两种方式

  1. 继承HandlerInterceptorAdapter的父类
  2. 实现HandlerInterceptor接口,实现的接口,推荐使用实现接口的方式

3. 拦截器实现的步骤

  1. 修改web.xml文件中请求路径

    <servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
    </servlet-mapping>
    
  2. 目录结构

  3. 改造登录方法,在session中存储用户信息,用于进行权限验证

    package com.shanglinsong.springmvc.controller;import com.shanglinsong.springmvc.pojo.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.http.HttpSession;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.controller.LearnInterceptor* @date 2023/1/29* @since 1.0*/
    @Controller
    public class LearnInterceptor {// 通过请求转发跳到WEB-INF目录下的资源上 login.jsp@RequestMapping(value = "/login", method = RequestMethod.GET)public String show(){return "login";}// 验证登录@RequestMapping(value = "/login", method = RequestMethod.POST)public String login(User user, HttpSession session){if ("admin".equalsIgnoreCase(user.getUsername()) && "admin".equalsIgnoreCase(user.getPassword())){// 将用户数据封装在session中session.setAttribute("user", user);// 跳转值主页return "main";}session.setAttribute("msg", "用户名或密码不正确");return "login";}// 访问主页@RequestMapping("/main")public String toMain(){return "main";}// 退出功能@RequestMapping("/logout")public String logout(HttpSession session){session.invalidate();return "login";}}
    
  4. 开发拦截器的功能。实现HandlerInterceptor接口,重写preHandle()方法

    package com.shanglinsong.springmvc.interceptor;import com.shanglinsong.springmvc.pojo.User;
    import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.springmvc.interceptor.LoginInterceptor* @date 2023/1/29* @since 1.0*/
    public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("=======================");// 通过取出session中的user对象,来判断是否登录过HttpSession session = request.getSession();User user = (User) session.getAttribute("user");if (null != user){return true;}// 不符合登录条件的请求,给出提示,打回到登录页面request.setAttribute("msg", "您还没有登录,请先登录");request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);return false;}
    }
    
  5. 在springmvc.xml文件中注册拦截器

    <!-- 注册拦截器 -->
    <mvc:interceptors><mvc:interceptor><!-- 配置拦截的路径(哪些请求被拦截) --><mvc:mapping path="/**"/><!-- 设置放行的请求 --><mvc:exclude-mapping path="/login"/><mvc:exclude-mapping path="/showLogin"/><!-- 设置进行功能处理的拦截器类 --><bean class="com.shanglinsong.springmvc.interceptor.LoginInterceptor"></bean></mvc:interceptor>
    </mvc:interceptors>
    
  • index.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 14:27To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>首页</title>
    </head>
    <body>
    <h1>欢迎进入系统!</h1>
    <form action="${pageContext.request.contextPath}/login"><input type="submit" value="点击进入登录界面">
    </form>
    </body>
    </html>
    

  • login.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 14:32To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>登录界面</title>
    </head>
    <body>
    <h2>登录</h2>
    <form action="${pageContext.request.contextPath}/login" method="post">用户名:<input type="text" name="username"><br>密  码:<input type="password" name="password"><br><input type="submit" value="登录">&nbsp;&nbsp;<input type="reset" value="重置">
    </form>
    <h3>${msg}</h3>
    </body>
    </html>
    

    • 直接通过url访问main

    • 输入错误

  • main.jsp

    <%--Created by IntelliJ IDEA.User: ShiningSongDate: 2023/1/29Time: 14:33To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>main</title>
    </head>
    <body>
    <h2>${user.getUsername()}好,欢迎回来</h2>
    <form action="${pageContext.request.contextPath}/logout"><input type="submit" value="退出登录">
    </form>
    </body>
    </html>
    

    • 点击退出登录返回至login界面,此时再通过url访问main

四、SSM整合的步骤

  1. 建库,建表

    • 使用Navicat执行语句生成数据库以及表

      /*Navicat Premium Data TransferSource Server         : zarSource Server Type    : MySQLSource Server Version : 80022Source Host           : localhost:3306Source Schema         : ssmusersTarget Server Type    : MySQLTarget Server Version : 80022File Encoding         : 65001Date: 26/06/2021 16:26:14
      */SET NAMES utf8mb4;
      SET FOREIGN_KEY_CHECKS = 0;CREATE DATABASE IF NOT EXISTS `ssmuser` DEFAULT CHARACTER SET utf8;
      USE `ssmuser`;-- ----------------------------
      -- Table structure for user
      -- ----------------------------
      DROP TABLE IF EXISTS `user`;
      CREATE TABLE `user`  (`user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',`card_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`card_no` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`user_sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`user_age` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`user_role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`user_id`) USING BTREE
      ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;-- ----------------------------
      -- Records of user
      -- ----------------------------
      INSERT INTO `user` VALUES ('15968162087363060', '身份证', '114264195202156467', '张三', '男', '30', '办事人员和有关人员');
      INSERT INTO `user` VALUES ('15968162346981977', '护照', 'A32532654', '李四', '男', '29', '不便分类的其他从业人员');
      INSERT INTO `user` VALUES ('15968162893439470', '身份证', '112344198709094532', '王五', '男', '31', '农、林、牧、渔、水利业生产人员');
      INSERT INTO `user` VALUES ('15968163245457143', '身份证', '453234199909094532', '赵六', '男', '34', '未知');
      INSERT INTO `user` VALUES ('15968163514764733', '军官证', '军7657868', '钱七', '女', '23', '不便分类的其他从业人员');
      INSERT INTO `user` VALUES ('15968165113694372', '台湾往来大陆通行证', '43256786', '周八', '女', '48', '生产、运输设备操作人员及有关人员');
      INSERT INTO `user` VALUES ('15968165371931786', '港澳居民通行证', 'C98767665', '吴九', '女', '35', '不便分类的其他从业人员');
      INSERT INTO `user` VALUES ('15968941217553030', '身份证', '343546199801018768', '郑十', '男', '22', '军人');
      INSERT INTO `user` VALUES ('15968943937844616', '身份证', '445453199603025756', '冯十一', '女', '31', '不便分类的其他从业人员');
      INSERT INTO `user` VALUES ('15968944123869023', '护照', 'B54322654', '陈十二', '女', '39', '农、林、牧、渔、水利业生产人员');
      INSERT INTO `user` VALUES ('15968953962316864', '身份证', '110232199505056789', '朱十三', '女', '33', '商业、服务业人员');
      INSERT INTO `user` VALUES ('15968954638794962', '身份证', '110654196604079098', '孔十四', '女', '29', '生产、运输设备操作人员及有关人员');SET FOREIGN_KEY_CHECKS = 1;
      
    • 执行结果

  2. 新建Maven项目,选择webapp模板

  3. 修改目录,完成结构如下:

  4. 修改pom.xml文件(使用老师提供)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.shanglinsong</groupId><artifactId>springmvc_007_ssm</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>springmvc_007_ssm Maven Webapp</name><url>http://maven.apache.org</url><!-- 集中定义依赖版本号 --><properties><junit.version>4.12</junit.version><spring.version>5.1.2.RELEASE</spring.version><mybatis.version>3.2.8</mybatis.version><mybatis.spring.version>1.2.2</mybatis.spring.version><mybatis.paginator.version>1.2.15</mybatis.paginator.version><mysql.version>8.0.17</mysql.version><slf4j.version>1.6.4</slf4j.version><druid.version>1.0.9</druid.version><pagehelper.version>5.1.2</pagehelper.version><jstl.version>1.2</jstl.version><servlet-api.version>3.0.1</servlet-api.version><jsp-api.version>2.0</jsp-api.version><jackson.version>2.9.6</jackson.version></properties><dependencies><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.11</version></dependency><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20140107</version></dependency><!-- spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis.spring.version}</version></dependency><dependency><groupId>com.github.miemiedev</groupId><artifactId>mybatis-paginator</artifactId><version>${mybatis.paginator.version}</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper.version}</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- 德鲁伊数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- jsp相关 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>${jstl.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>${servlet-api.version}</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><version>${jsp-api.version}</version></dependency><!-- json处理工具包 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version></dependency><!-- 文件上传用 --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency></dependencies><build><finalName>springmvc_007_ssm</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin></plugins><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes><filtering>false</filtering></resource></resources></build>
    </project>
    
  5. 添加jdbc.properties属性文件

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/ssmuser?serverTimezone=Asia/Shanghai
    jdbc.username=root
    jdbc.password=123
    
  6. 添加SqlMapConfig.xml文件(使用模板)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration><!--设置日志输出语句,显示相应操作的sql语名--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><!-- 分页插件 --><!--<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>-->
    </configuration>
    
  7. 添加applicationContext_mapper.xml文件(数据访问层的核心配置文件)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 读取jdbc.properties属性文件 --><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!-- 创建数据源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 创建SqlSessionFactoryBean --><bean class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 配置数据源 --><property name="dataSource" ref="dataSource"></property><!-- 配置mybatis的核心配置文件 --><property name="configLocation" value="classpath:SqlMapConfig.xml"></property><!--注册实体类--><property name="typeAliasesPackage" value="com.shanglinsong.ssm.pojo"></property></bean><!-- 创建mapper文件的扫描器--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.shanglinsong.ssm.mapper"></property></bean>
    </beans>
    
  8. 添加applicationContext_service.xml文件(业务逻辑层的核心配置文件)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 设置业务逻辑层的包扫描器, 目的是在指定路径下,使用@Service注解的类,Spring负责创建对象,并添加依赖--><context:component-scan base-package="com.shanglinsong.ssm.service.impl"></context:component-scan><!-- 设置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 添加事务切面 --><tx:advice id="myadvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*select*" read-only="true"/><tx:method name="*find*" read-only="true"/><tx:method name="*get*" read-only="true"/><tx:method name="*search*" read-only="true"/><tx:method name="*insert*" propagation="REQUIRED"/><tx:method name="*save*" propagation="REQUIRED"/><tx:method name="*add*" propagation="REQUIRED"/><tx:method name="*delete*" propagation="REQUIRED"/><tx:method name="*remove*" propagation="REQUIRED"/><tx:method name="*drop*" propagation="REQUIRED"/><tx:method name="*clear*" propagation="REQUIRED"/><tx:method name="*update*" propagation="REQUIRED"/><tx:method name="*modify*" propagation="REQUIRED"/><tx:method name="*change*" propagation="REQUIRED"/><tx:method name="*set*" propagation="REQUIRED"/><tx:method name="**" propagation="SUPPORTS"/></tx:attributes></tx:advice><!-- 完成切面的切入点和织入 --><aop:config><aop:pointcut id="mypointcut" expression="execution(* com.shanglinsong.ssm.service.impl.*.*(..))"/><aop:advisor advice-ref="myadvice" pointcut-ref="mypointcut"></aop:advisor></aop:config></beans>
    
  9. 添加spirngmvc.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 添加包扫描器 --><context:component-scan base-package="com.shanglinsong.ssm.controller"></context:component-scan><!-- 添加视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- 前缀 --><property name="prefix" value="/admin/"></property><!-- 后缀 --><property name="suffix" value=".jsp"></property></bean><!-- 设置文件上传核心组件 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean><!-- 设置注解驱动 --><mvc:annotation-driven></mvc:annotation-driven><!-- 解决跨域问题 --><mvc:cors><mvc:mapping path="/**"allowed-origins="*"allowed-methods="POST,GET,OPTIONS,DELETE,PUT"allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"allow-credentials="true"></mvc:mapping></mvc:cors></beans>
    
    • 注意解决跨域问题.

    什么是跨域?

    浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域.

    域名:

    主域名不同 http://www.baidu.com/index.html -->http://www.sina.com/test.js

    子域名不同 http://www.666.baidu.com/index.html -->http://www.555.baidu.com/test.js

    域名和域名ip http://www.baidu.com/index.html -->http://180.149.132.47/test.js

    端口:

    http://www.baidu.com:8080/index.html–> http://www.baidu.com:8081/test.js

    协议:

    http://www.baidu.com:8080/index.html–> https://www.baidu.com:8080/test.js

    备注:

    1. 端口和协议的不同,只能通过后台来解决
    2. localhost和127.0.0.1虽然都指向本机,但也属于跨域
    3. 另外一种解决方案是在控制器上添加@CrossOrigin注解.
    4. 或者自定义过滤器,进行跨域处理.
  10. 删除web.xml文件,新建,改名,设置中文编码,并注册spirngmvc框架,并注册Spring框架

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 添加字符编码过滤器 --><filter><filter-name>encode</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!--private String encoding;private boolean forceRequestEncoding;private boolean forceResponseEncoding;--><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encode</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 注册SpringMVC框架 --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 注册Spring框架 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext_*.xml</param-value></context-param></web-app>
    
  11. 新建实体类user

    package com.shanglinsong.ssm.pojo;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.pojo.User* @date 2023/1/29* @since 1.0*/
    public class User {private String userId; // 用户idprivate String cardType; // 证件类型private String cardNo; // 证件号码private String userName; // 用户姓名private String userSex; // 用户性别private String userAge; // 用户年龄private String userRole; // 用户角色@Overridepublic String toString() {return "User{" +"userId='" + userId + '\'' +", cardType='" + cardType + '\'' +", cardNo='" + cardNo + '\'' +", userName='" + userName + '\'' +", userSex='" + userSex + '\'' +", userAge='" + userAge + '\'' +", userRole='" + userRole + '\'' +'}';}public User() {}public User(String userId, String cardType, String cardNo, String userName, String userSex, String userAge, String userRole) {this.userId = userId;this.cardType = cardType;this.cardNo = cardNo;this.userName = userName;this.userSex = userSex;this.userAge = userAge;this.userRole = userRole;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getCardType() {return cardType;}public void setCardType(String cardType) {this.cardType = cardType;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserSex() {return userSex;}public void setUserSex(String userSex) {this.userSex = userSex;}public String getUserAge() {return userAge;}public void setUserAge(String userAge) {this.userAge = userAge;}public String getUserRole() {return userRole;}public void setUserRole(String userRole) {this.userRole = userRole;}
    }
    
  12. 新建UserMapper.java接口

    package com.shanglinsong.ssm.mapper;import com.shanglinsong.ssm.pojo.User;
    import org.apache.ibatis.annotations.Param;import java.util.List;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.mapper.UserMapper* @date 2023/1/29* @since 1.0*/
    public interface UserMapper {/*** 分页查询 User* @param startRows 起始页* @return*/List<User> queryUserPage(Integer startRows);/*** 分页查询 User 带条件* @param userName* @param userSex* @param startRows* @return*/List<User> selectUserPage(@Param("userName")String userName,@Param("userSex")String userSex,@Param("startRows")Integer startRows);/*** 查询 User 个数* @param userName* @param userSex* @return*/Integer getRowCount(@Param("userName")String userName,@Param("userSex")String userSex);/*** 添加 User* @param user* @return*/Integer createUser(User user);/*** 根据 userId 删除 User* @param userId* @return*/Integer deleteUserById(String userId);/*** 根据 userId 批量删除 User* @param userIds* @return*/Integer deleteUserByIdList(@Param("list")List userIds);/*** 根据 userId 更新 User* @param user* @return*/Integer updateUserById(User user);
    }
    
  13. 新建UserMapper.xml实现增删改查所有功能

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.shanglinsong.ssm.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.shanglinsong.ssm.pojo.User"><id property="userId" column="user_id" jdbcType="VARCHAR"></id><result property="cardType" column="card_type" jdbcType="VARCHAR"></result><result property="cardNo" column="card_no" jdbcType="VARCHAR"></result><result property="userName" column="user_name" jdbcType="VARCHAR"></result><result property="userSex" column="user_sex" jdbcType="VARCHAR"></result><result property="userAge" column="user_age" jdbcType="VARCHAR"></result><result property="userRole" column="user_role" jdbcType="VARCHAR"></result></resultMap><sql id="Base_Column_List">user_id, card_type, card_no, user_name, user_sex, user_age, user_role</sql><!--分页查询 UserList<User> queryUserPage(Integer startRows);--><select id="queryUserPage" resultMap="BaseResultMap" parameterType="Integer">select<include refid="Base_Column_List"/>from userorder by user_id desclimit #{startRows, jdbcType=INTEGER}, 5</select><!--分页查询 User 带条件List<User> selectUserPage(@Param("userName")String userName,@Param("userSex")String userSex,@Param("startRows")String startRows);--><select id="selectUserPage" resultMap="BaseResultMap">select<include refid="Base_Column_List"/>from user<where><if test="userName != null and userName != ''">and user_name like concat("%", #{userName}, "%")</if><if test="userSex != null and userSex != ''">and user_sex = #{userSex}</if></where>order by user_id desclimit #{startRows, jdbcType=INTEGER}, 5</select><!--查询 User 个数Integer getRowCount(@Param("userName")String userName,@Param("userSex")String userSex);--><select id="getRowCount" resultType="java.lang.Integer">select count(*) from user<where><if test="userName != null and userName != ''">and user_name like concat("%", #{userName}, "%")</if><if test="userSex != null and userSex != ''">and user_sex = #{userSex}</if></where></select><!--添加 UserInteger createUser(User user);--><insert id="createUser" parameterType="com.shanglinsong.ssm.pojo.User">insert into user (<include refid="Base_Column_List"/>)values (#{userId}, #{cardType}, #{cardNo}, #{userName}, #{userSex}, #{userAge}, #{userRole})</insert><!--根据 userId 删除 UserInteger deleteUserById(String userId);--><delete id="deleteUserById" parameterType="String">delete from userwhere user_id = #{userId, jdbcType=VARCHAR}</delete><!--根据 userId 批量删除 UserInteger deleteUserByIdList(@Param("list")List userIds);--><delete id="deleteUserByIdList" parameterType="java.util.List">delete from userwhere user_id in<foreach collection="list" item="item" index="index" open="(" close=")" separator=",">#{item, jdbcType=VARCHAR}</foreach></delete><!--根据 userId 更新 UserInteger updateUserById(User user);--><update id="updateUserById" parameterType="com.shanglinsong.ssm.pojo.User">update user<set><if test="cardNo != null">card_no = #{cardNo, jdbcType=VARCHAR},</if><if test="cardType != null">card_type = #{cardType, jdbcType=VARCHAR},</if><if test="userName != null">user_name = #{userName, jdbcType=VARCHAR},</if><if test="userSex != null">user_sex = #{userSex, jdbcType=VARCHAR},</if><if test="userAge != null">user_age = #{userAge, jdbcType=VARCHAR},</if><if test="userRole != null">user_role = #{userRole, jdbcType=VARCHAR}</if></set>where 1 = 1and user_id = #{userId, jdbcType=VARCHAR}</update>
    </mapper>
    
  14. 新建service接口和实现类

    • com.shanglinsong.ssm.service.UserService

      package com.shanglinsong.ssm.service;import com.shanglinsong.ssm.pojo.User;
      import org.apache.ibatis.annotations.Param;import java.util.List;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.service.UserService* @date 2023/1/30* @since 1.0*/
      public interface UserService {/*** 分页查询 User* @param startRows 起始页* @return*/List<User> queryUserPage(Integer startRows);/*** 分页查询 User 带条件* @param userName* @param userSex* @param startRows* @return*/List<User> selectUserPage(@Param("userName")String userName,@Param("userSex")String userSex,@Param("startRow")Integer startRows);/*** 查询 User 个数* @param userName* @param userSex* @return*/Integer getRowCount(@Param("userName")String userName,@Param("userSex")String userSex);/*** 添加 User* @param user* @return*/Integer createUser(User user);/*** 根据 userId 删除 User* @param userId* @return*/Integer deleteUserById(String userId);/*** 根据 userId 批量删除 User* @param userIds* @return*/Integer deleteUserByIdList(@Param("list")List userIds);/*** 根据 userId 更新 User* @param user* @return*/Integer updateUserById(User user);
      }
      
    • com.shanglinsong.ssm.service.impl.UserServiceImpl

      package com.shanglinsong.ssm.service.impl;import com.shanglinsong.ssm.mapper.UserMapper;
      import com.shanglinsong.ssm.pojo.User;
      import com.shanglinsong.ssm.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;import java.util.List;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.service.impl.UserServiceImpl* @date 2023/1/30* @since 1.0*/
      @Service
      public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> queryUserPage(Integer startRows) {return userMapper.queryUserPage(startRows);}@Overridepublic List<User> selectUserPage(String userName, String userSex, Integer startRows) {return userMapper.selectUserPage(userName, userSex, startRows);}@Overridepublic Integer getRowCount(String userName, String userSex) {return userMapper.getRowCount(userName, userSex);}@Overridepublic Integer createUser(User user) {return userMapper.createUser(user);}@Overridepublic Integer deleteUserById(String userId) {return userMapper.deleteUserById(userId);}@Overridepublic Integer deleteUserByIdList(List userIds) {return userMapper.deleteUserByIdList(userIds);}@Overridepublic Integer updateUserById(User user) {return userMapper.updateUserById(user);}
      }
      
  15. 新建测试类,完成所有功能的测试

    • 完整代码

      package com.shanglinsong.ssm.test;import com.shanglinsong.ssm.pojo.User;
      import com.shanglinsong.ssm.service.UserService;
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.ArrayList;
      import java.util.List;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.test.SSMTest* @date 2023/1/30* @since 1.0*/
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = {"classpath:applicationContext_mapper.xml", "classpath:applicationContext_service.xml"})
      public class SSMTest {@Autowiredprivate UserService userService;// 根据 userId 更新 User@Testpublic void testUpdateUserById(){User updateUser = new User("22222222222", "发财证", "888888888888888888", "shanglinsong", "男", "30", "架构师");Integer count = userService.updateUserById(updateUser);System.out.println(count == 1? "修改命运成功!": "修改失败!继续加油吧!");}// 根据 userId 批量删除 User@Testpublic void testDeleteUserByIdList(){ArrayList<String> userIds = new ArrayList<>();userIds.add("12345678910");userIds.add("12345678911");userIds.add("22222222222");// System.out.println(userIds);Integer count = userService.deleteUserByIdList(userIds);System.out.println(count == 3 ? "删除成功!": "删除失败!");}// 根据 userId 删除 User@Testpublic void testDeleteUserById(){Integer count = userService.deleteUserById("12345678910");System.out.println(count == 1 ? "幸运星删除成功": "幸运星删除失败");count += userService.deleteUserById("12345678911");System.out.println(count == 2 ? "倒霉蛋删除成功": "倒霉蛋删除失败");count += userService.deleteUserById("22222222222");System.out.println(count == 3 ? "二逼shanglinsong删除成功": "二逼shanglinsong删除失败");}//添加 User/*private String userId; // 用户idprivate String cardType; // 证件类型private String cardNo; // 证件号码private String userName; // 用户姓名private String userSex; // 用户性别private String userAge; // 用户年龄private String userRole; // 用户角色*/@Testpublic void testCreateUser(){User user1 = new User("12345678910", "身份证", "66666620000101662X", "幸运星", "女", "23", "董事长");User user2 = new User("12345678911", "身份证", "44444419991231221X", "倒霉蛋", "男", "23", "研究僧");User user3 = new User("22222222222", "二逼证", "222222222222222222", "shanglinsong", "男", "26", "无业游民");Integer count = userService.createUser(user1);System.out.println(count == 1 ? "幸运星添加成功": "幸运星添加失败");count += userService.createUser(user2);System.out.println(count == 2 ? "倒霉蛋添加成功": "倒霉蛋添加失败");count += userService.createUser(user3);System.out.println(count == 3 ? "二逼shanglinsong添加成功": "二逼shanglinsong添加失败");}// 查询 User 个数@Testpublic void testGetRowCount(){Integer rowCount = userService.getRowCount(null, null);System.out.println("一共有" + rowCount + "条记录");}// 分页查询 User 带条件@Testpublic void testSelectUserPage(){List<User> users = userService.selectUserPage("十", "女", 0);users.forEach(user -> System.out.println(user));}// 分页查询 User@Testpublic void testQueryUserPage(){List<User> users = userService.queryUserPage(0);users.forEach(user -> System.out.println(user));}
      }
      
    • 分页查询 User

      @Test
      public void testQueryUserPage(){List<User> users = userService.queryUserPage(0);users.forEach(user -> System.out.println(user));
      }
      

      执行结果:

    • 分页查询 User 带条件

      @Test
      public void testSelectUserPage(){List<User> users = userService.selectUserPage("十", "女", 0);users.forEach(user -> System.out.println(user));
      }
      

      执行结果:

    • 查询 User 个数

      @Test
      public void testGetRowCount(){Integer rowCount = userService.getRowCount(null, null);System.out.println("一共有" + rowCount + "条记录");
      }
      

      执行结果:

    • 添加 User

      /*private String userId; // 用户idprivate String cardType; // 证件类型private String cardNo; // 证件号码private String userName; // 用户姓名private String userSex; // 用户性别private String userAge; // 用户年龄private String userRole; // 用户角色
      */
      @Test
      public void testCreateUser(){User user1 = new User("12345678910", "身份证", "66666620000101662X", "幸运星", "女", "23", "董事长");User user2 = new User("12345678911", "身份证", "44444419991231221X", "倒霉蛋", "男", "23", "研究僧");User user3 = new User("22222222222", "二逼证", "222222222222222222", "shanglinsong", "男", "26", "无业游民");Integer count = userService.createUser(user1);System.out.println(count == 1 ? "幸运星添加成功": "幸运星添加失败");count += userService.createUser(user2);System.out.println(count == 2 ? "倒霉蛋添加成功": "倒霉蛋添加失败");count += userService.createUser(user3);System.out.println(count == 3 ? "二逼shanglinsong添加成功": "二逼shanglinsong添加失败");
      }
      

      执行结果:

    • 根据 userId 删除 User

      @Test
      public void testDeleteUserById(){Integer count = userService.deleteUserById("12345678910");System.out.println(count == 1 ? "幸运星删除成功": "幸运星删除失败");count += userService.deleteUserById("12345678911");System.out.println(count == 2 ? "倒霉蛋删除成功": "倒霉蛋删除失败");count += userService.deleteUserById("22222222222");System.out.println(count == 3 ? "二逼shanglinsong删除成功": "二逼shanglinsong删除失败");
      }
      

      执行结果:

    • 根据 userId 批量删除 User(再利用添加 User 测试重新添加3个用户)

      @Test
      public void testDeleteUserByIdList(){ArrayList<String> userIds = new ArrayList<>();userIds.add("12345678910");userIds.add("12345678911");userIds.add("22222222222");// System.out.println(userIds);Integer count = userService.deleteUserByIdList(userIds);System.out.println(count == 3 ? "删除成功!": "删除失败!");
      }
      

      执行结果:

    • 根据 userId 更新 User

      @Test
      public void testUpdateUserById(){User updateUser = new User("22222222222", "发财证", "888888888888888888", "shanglinsong", "男", "30", "架构师");Integer count = userService.updateUserById(updateUser);System.out.println(count == 1? "修改命运成功!": "修改失败!继续加油吧!");
      }
      

      执行结果:

  16. 新建控制器,完成所有功能

    package com.shanglinsong.ssm.controller;import com.shanglinsong.ssm.pojo.User;
    import com.shanglinsong.ssm.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;/*** @author shanglinsong* @version 1.0* @className com.shanglinsong.ssm.controller.UserController* @date 2023/1/30* @since 1.0*/
    @CrossOrigin
    @RestController
    @RequestMapping("user")
    public class UserController {@Autowiredprivate UserService userService;// 分页查询 User@RequestMapping("/queryUserPage")public List<User> queryUserPage(Integer page){// 计算分页查询开始行int pageNow = page == null ? 1 : page;int pageSize = 5;int startRows = pageSize*(page-1);return userService.queryUserPage(startRows);}// 分页查询 User 带条件@RequestMapping("/selectUserPage")public List<User> selectUserPage(String userName, String userSex, Integer page){// 计算分页查询开始行int pageNow = page == null ? 1 : page;int pageSize = 5;int startRows = pageSize*(page-1);return userService.selectUserPage(userName, userSex, startRows);}// 查询 User 个数@RequestMapping("/getRowCount")public Integer getRowCount(String userName, String userSex){return userService.getRowCount(userName, userSex);}// 添加 User@RequestMapping("/createUser")public Integer createUser(User user){// 生成随机userIdRandom random = new Random();Integer userId = random.nextInt(9000) + 1000;user.setUserId(System.currentTimeMillis() + String.valueOf(userId));return userService.createUser(user);}// 根据 userId 删除 User@RequestMapping("/deleteUserById")public Integer deleteUserById(String userId){return userService.deleteUserById(userId);}// 根据 userId 批量删除 User// 当映射名称不一样时需要使用@RequestParam注解// 由于没有看文档才出现这个问题,工作中一定要按照文档办事!@RequestMapping("/deleteUserByIdList")public Integer deleteUserByIdList(@RequestParam("userIdList")String userIds){// System.out.println("==========");// System.out.println(userIds);// 去除最后的","String userIdsSub = userIds.substring(0, userIds.length() - 1);// 创建List存放userIdsArrayList<String> userIdsList = new ArrayList<>();for (String userId : userIdsSub.split(",")){userIdsList.add(userId.trim());}// System.out.println(userIdsList);return userService.deleteUserByIdList(userIdsList);}// 根据 userId 更新 User@RequestMapping("/updateUserById")public Integer updateUserById(User user){return userService.updateUserById(user);}
    }
    
  17. 浏览器测试功能

    • 安装node.js, 使用提供好的vue素材。本人使用VScode运行,此笔记不涉及vue技术,因此不做idea构建vue项目和vue具体细节内容的记录。

    • 查看版本编号

      node -v
      npm –v
      

      node.js的安装是为了使当前的计算机使用vue的框架,预安装的工具。有点类似于运行java程序时必须安装JDK一样的道理。

    • 构建项目

      使用命令行进入到当前要运行的vue的项目的目录下,运行以下命令进行项目搭建.

      1. 进入到当前项目的目录下
      2. npm i element -ui -S 下载elementUI的框架
      3. npm install //打包项目
      4. npm install --save vue-axios //下载跨域访问组件axios
    • 设计好的vue项目访问服务器的端口号为8082,但本人使用tomca启动时idea报不能采用该端口进行发布,因此进入vue项目目录下的 /config/index.js 文件中对target进行修改,将端口号改为8080

    • 使用idea配置好tomcat启动后端服务器,端口号8080(如果先启动vue项目,vue项目会占用8080端口号,先启动tomcat再启动vue项目,vue项目将自动分配至8081端口,本人对vue不是很了解,目前说不清楚原因,所以就不在此暴露自己的无知了哈哈,等后面在好好学习一下吧,加油!)

    • 点击“查看”–>“终端”调出终端,由于该项目设置dev方式启动,因此输入以下命令启动项目

      npm run dev
      

      启动后终端显示:

      使用该网址进入vue项目主页:

    • 点击UserHome进入操作界面

      • 分页查询功能

      • 条件分页查询功能

      • 添加用户功能

      • 删除用户功能

      • 编辑(更新)信息功能

      • 批量删除功能

[记录学习]自学动力节点荣姐SpringMVC5笔记相关推荐

  1. [记录学习]自学动力节点老杜Spring6笔记_01

    首先感谢动力节点和杜老师的教学分享!Respect! 学习来源:B站 https://www.bilibili.com/video/BV1Ft4y1g7Fb/?spm_id_from=333.337. ...

  2. [记录学习]自学动力节点老杜Spring6笔记_02

    首先感谢动力节点和杜老师的教学分享!Respect! 学习来源:B站 https://www.bilibili.com/video/BV1Ft4y1g7Fb/?spm_id_from=333.337. ...

  3. SpringMVC总结(动力节点荣姐)

  4. 2022全新Java学习路线图动力节点(一)Java学前准备工作

    动力节点2022最新的LOL版Java学习路线图来了!!!准备做一个系列文章,强烈建议大家收藏起来,是时候学习真正的Java技术了! 楔子 这天,符文之地被Java编程全面同化,EZ为了适应新世界,开 ...

  5. 2022全新Java学习路线图动力节点(五)框架之路

    五.框架之路-丛林沙漠巨神峰 框架技术 送君千里终须一别,拜别了厄运小姐和格雷福斯的盛情挽留,在目送了崔斯特开大消失后,ez在哈雷尔港驻足了片刻便启程前往以绪奥肯.他摸了摸纳袋(空间口袋),里面是菲兹 ...

  6. 2022全新Java学习路线图动力节点(八)Java选学的技术有哪些?

    八.失落之地的辉煌 这里曾经繁华一片,被世人称作福光,搁在古老的东方就叫洞天福地!但现在一切都烟消云散,一场魔法灾难让此地化作焦土,沦为人间炼狱.此地长年被黑暗浓雾笼罩,即便世界被同化之后也没能改变土 ...

  7. 2022全新Java学习路线图动力节点(二)Java基础

    先上干货,再讲故事.召唤师,准备好你的键盘了吗?开战吧! 二.北地禁魔 Java零基础需要掌握的技术 背景故事: 世界被同化之后,符文之地有些地区发生了变化.首当其中的便是德邦与北地.两地边界渐融,在 ...

  8. 2022全新Java学习路线图动力节点(六)分布式

    六.初生之地的崛起 分布式技术 背景故事: 普雷西典,艾瑞莉娅正挥舞着Dubbo翩翩起舞.自从有了它,刀阵变得更加如臂指使,每每舞动也更添韵律.抢到分布式十几项神技,艾欧尼亚有如神助,苦日子终于要熬出 ...

  9. 2022全新Java学习路线图动力节点(三)数据库

      三.帝国的野望 数据库所学技术 背景故事: 世界同化之后,诺克萨斯抢先窃取了数据库并进一步打算与艾欧尼亚争夺分布式神技,并在恕瑞玛抢夺框架.诺克萨斯多线开战,显然野心不小. 德莱厄斯目前正在前线处 ...

最新文章

  1. python连接linux获取日志_Python 日志记录模块logging的使用
  2. 火狐浏览器服务器意外响应,Firefox 火狐浏览器 83 发布,已修复任意代码执行漏洞...
  3. teamcity_TeamCity工件:HTTP,Ant,Gradle和Maven
  4. 【渝粤题库】陕西师范大学202071 统计学 作业(专升本、高起本)
  5. 奥鹏17计算机应用基础离线,奥鹏《计算机应用基础》离线
  6. 解决ubuntu下的firefox无法在线播放音频和视频的问题
  7. python vb 哪个好学_最难学的七大编程语言,VB 第一,Python垫底,看你学的排第几...
  8. CentOS 非图形界面用户如何上网
  9. 华为根本没有鸿蒙系统,【图片】你看不明白的鸿蒙系统,才是华为缔造未来的“伟大”!华为并没有把系统划分为手机操作系统,我们就能知道华为想的并不是那么简单【手机吧】_百度贴吧...
  10. 让人死去活来的cocos2d-x安卓开发环境搭建(windows+eclipse+ndk 不用cygwin)【上图】
  11. C++题解:百钱买百鸡数量
  12. 工业机器人 郝卫东_基于S3C2410的视觉巡线机器人系统设计
  13. 渐变色【R Color】
  14. excel求回归直线方程的公式_如何用excel做线性回归分析-用excel做线性回归分析求回归方程...
  15. 部分选主元matlab,列选主元的高斯消去法-matlab
  16. 指针游戏1 最简单的指针游戏
  17. 海信JAVA开发笔试题_JAVA设计模式之【工厂方法模式】
  18. matlab 天线设计 泰勒加权_泰勒加权功分器
  19. 我的世界java版特别卡怎么办_我的世界卡顿延迟怎么办
  20. Fortran(X)概述

热门文章

  1. C++ substr()函数
  2. Word和Excel中的常用办公操作
  3. 解析android:ellipsize=end属性无效的情况
  4. maya python插件_Maya Python - ALembic导入导出助手
  5. android设置图片长宽比例,【教程】安卓保证图片长宽比的同时拉伸图片
  6. 详解HBase架构原理
  7. 变压器的这些特性,你了解多少?
  8. 信号与系统——基本概念
  9. 【目标检测】Anchor Free —— OneNet(不需要NMS)
  10. linux-rootkit