[记录学习]自学动力节点荣姐SpringMVC5笔记

首先感谢动力节点和老师的教学分享!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 学习笔记

一、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/one
          http://localhost:8080/index.jsp
          http://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: ShiningSong
      Date: 2023/1/22
      Time: 18:31
      To 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: ShiningSong
      Date: 2023/1/22
      Time: 18:34
      To 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 setter
        constructor
        toString
    }
    
    • 页面:
    <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: ShiningSong
      Date: 2023/1/28
      Time: 16:48
      To 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")
        @ResponseBody
        public 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: ShiningSong
        Date: 2023/1/28
        Time: 19:06
        To 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.action
              return "forward:/other.action";   //不使用forward:,就会是这样的路径  /admin/other.action/.jsp
          }
          @RequestMapping("/three")
          public String three(){
              System.out.println("重定向页面");
              //观察地址栏的变化  http://localhost:8080/admin/main.jsp
              return "redirect:/admin/main.jsp";//只要使用了redirect:就可以屏蔽前缀和后缀的拼接
          }
          @RequestMapping("/four")
          public String four(){
              System.out.println("重定向action");
              //观察地址栏的变化  http://localhost:8080/other.action
              return "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: ShiningSong
        Date: 2023/1/28
        Time: 19:11
        To 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: ShiningSong
      Date: 2023/1/29
      Time: 10:14
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 10:47
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 10:56
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 10:57
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 10:58
      To 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 {
        @Override
        public 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: ShiningSong
      Date: 2023/1/29
      Time: 14:27
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 14:32
      To 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: ShiningSong
      Date: 2023/1/29
      Time: 14:33
      To 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 Transfer
      
       Source Server         : zar
       Source Server Type    : MySQL
       Source Server Version : 80022
       Source Host           : localhost:3306
       Source Schema         : ssmusers
      
       Target Server Type    : MySQL
       Target Server Version : 80022
       File Encoding         : 65001
      
       Date: 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 configuration
            PUBLIC "-//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; // 用户id
        private String cardType; // 证件类型
        private String cardNo; // 证件号码
        private String userName; // 用户姓名
        private String userSex; // 用户性别
        private String userAge; // 用户年龄
        private String userRole; // 用户角色
    
        @Override
        public 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 mapper
            PUBLIC "-//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>
        <!--
            分页查询 User
            List<User> queryUserPage(Integer startRows);
        -->
        <select id="queryUserPage" resultMap="BaseResultMap" parameterType="Integer">
            select
                <include refid="Base_Column_List"/>
                from user
                order by user_id desc
                limit #{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 desc
                limit #{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>
    
        <!--
            添加 User
            Integer 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 删除 User
            Integer deleteUserById(String userId);
        -->
        <delete id="deleteUserById" parameterType="String">
            delete from user
            where user_id = #{userId, jdbcType=VARCHAR}
        </delete>
    
        <!--
            根据 userId 批量删除 User
            Integer deleteUserByIdList(
                @Param("list")
                List userIds
            );
        -->
        <delete id="deleteUserByIdList" parameterType="java.util.List">
            delete from user
                where user_id in
                    <foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
                        #{item, jdbcType=VARCHAR}
                    </foreach>
        </delete>
    
        <!--
            根据 userId 更新 User
            Integer 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 = 1
                and 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 {
      
          @Autowired
          private UserMapper userMapper;
      
          @Override
          public List<User> queryUserPage(Integer startRows) {
              return userMapper.queryUserPage(startRows);
          }
      
          @Override
          public List<User> selectUserPage(String userName, String userSex, Integer startRows) {
              return userMapper.selectUserPage(userName, userSex, startRows);
          }
      
          @Override
          public Integer getRowCount(String userName, String userSex) {
              return userMapper.getRowCount(userName, userSex);
          }
      
          @Override
          public Integer createUser(User user) {
              return userMapper.createUser(user);
          }
      
          @Override
          public Integer deleteUserById(String userId) {
              return userMapper.deleteUserById(userId);
          }
      
          @Override
          public Integer deleteUserByIdList(List userIds) {
              return userMapper.deleteUserByIdList(userIds);
          }
      
          @Override
          public 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 {
      
          @Autowired
          private UserService userService;
      
          // 根据 userId 更新 User
          @Test
          public void testUpdateUserById(){
              User updateUser = new User("22222222222", "发财证", "888888888888888888", "shanglinsong", "男", "30", "架构师");
              Integer count = userService.updateUserById(updateUser);
              System.out.println(count == 1? "修改命运成功!": "修改失败!继续加油吧!");
          }
      
          // 根据 userId 批量删除 User
          @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 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; // 用户id
              private 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添加失败");
          }
      
          // 查询 User 个数
          @Test
          public void testGetRowCount(){
              Integer rowCount = userService.getRowCount(null, null);
              System.out.println("一共有" + rowCount + "条记录");
          }
      
          // 分页查询 User 带条件
          @Test
          public void testSelectUserPage(){
              List<User> users = userService.selectUserPage("十", "女", 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 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; // 用户id
          private 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 {
    
        @Autowired
        private 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){
            // 生成随机userId
            Random 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存放userIds
            ArrayList<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进入操作界面

      在这里插入图片描述

      • 分页查询功能

        在这里插入图片描述

      • 条件分页查询功能

        在这里插入图片描述

      • 添加用户功能

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

      • 删除用户功能

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

      • 编辑(更新)信息功能

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

      在这里插入图片描述

      • 批量删除功能

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值