[SSM]SpringMVC详解

news2024/11/24 1:36:19

目录

一、SpringMVC简介 

1.1什么是MVC

1.2什么是SpringMVC

1.3SpringMVC优点

1.4SpringMVC优化的方向

1.5SpringMVC执行的流程

1.6基于注解的SpringMVC程序

二、SpringMVC注解式开发

2.1@RequestMapping定义请求规则

2.1.1指定模块名称

2.1.2对请求提交方式的定义

2.2五种数据提交的方式

2.2.1单个数据注入

2.2.2对象封装注入

2.2.3动态占位符提交(仅用于超链接)

2.2.4请求参数名称与形参名称不一致

2.2.5使用HttpServletRequest对象提取

​编辑2.3请求参数中文乱码解决

2.3.1解决方案

2.3.2源码分析

2.4处理器方法的返回值

2.4.1返回ModelAndView(较少使用)

2.4.2返回String

2.4.3无返回值void

2.4.4返回对象Object

2.5SpringMVC的四种跳转方式

2.6SpringMVC支持的默认参数类型

2.7日期处理

2.7.1日期注入

2.7.2日期显示

2.8标签的使用

2.9资源在WEB-INF目录下

三、SpringMVC拦截器

3.1拦截器介绍

3.1.1拦截器的应用场景

3.1.2拦截器的执行原理

3.1.3拦截器执行的时机

3.1.4拦截器实现的两种方式

3.2自定义拦截器实现权限验证

四、SSM整合

4.1SSM整合后台功能

(1)新建Maven项目,添加依赖

(2)拷贝所有的配置文件到config,开发每个配置文件

(3)在web.xml文件中完成springmvc,spring两个框架的注册

(4)创建实体类对象User

(5)创建UserMapper接口和实现功能的UserMapper.xml

(6)创建业务逻辑层UserService接口和实现类

(7)创建测试类进行功能测试

(8)创建action进行分页显示,查询用户个数,删除处理

4.2Vue实现前台功能

(1)安装node.js

(2)构建项目

(3)为idea添加vue插件

(4)配置启动项

(5)项目结构

(6)UserHome.vue解读


一、SpringMVC简介 

1.1什么是MVC

  • MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分。

  • M:Model,模型层,指工程中的JavaBean,作用是处理数据。

    • JavaBean分为两类:

      • 一类称为实体类Bean:专门存储业务数据的,如Student、User等。

      • 一类称为业务处理Bean:指Service或Dao对象,专门用于处理业务逻辑和数据访问。

  • V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据

  • C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器。

  • MVC的工作流程:用户通过视图层发生请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器。

1.2什么是SpringMVC

  • 它是基于MVC开发模式的框架,用来优化控制器。

  • 它是Spring家族的一员,它也具备IOC和AOP。

1.3SpringMVC优点

  • 基于MVC架构

    • 基于MVC架构,功能分工明确,解耦合。

  • 容易理解,上手快,使用简单

    • SpringMVC是轻量级的,jar很小。不依赖特定的接口和类。

  • 作为Spring框架的一部分,能够使用Spring的IOC和AOP

    • 方便整合Strtus、MyBatis、Hiberate、JPA等其它框架。

  • SpringMVC强化注解的使用

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

1.4SpringMVC优化的方向

  • 数据提交的优化

  • 携带数据的优化

  • 简化返回处理

1.5SpringMVC执行的流程

  • 执行流程说明:

    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. 视图负责将渲染结果返回给客户端。

1.6基于注解的SpringMVC程序

  • 所谓SpringMVC的注解式开发是指,在代码中通过对类与方法的注解,便可完成处理器在springmvc容器的注册。注解式开发是重点。

  • 项目案例:用户提交一个请求,服务端处理器在接收到这个请求后,给出一条欢迎信息,在响应页面中显示该信息。

  • 创建步骤:

    1. 新建maven_web项目

    2. 添加依赖

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.5.RELEASE</version>
      </dependency>
      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      </dependency>

    3. 删除web.xml文件重新添加,因为自动生成的web.xml文件版本太低了。

    4. 在web.xml文件中注册SpringMVC框架。因为web的请求都是由Servlet来进行处理的,而SpringMVC的核心处理器就是一个DispatcherServlet,它负责接收客户端的请求,并根据请求的路径分派给对应的action(控制器)进行处理,处理结束后依然由核心处理器DispatcherServlet进行响应返回。

      <!--注册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>*.action</url-pattern>
      </servlet-mapping>

    5. 删除index.jsp页面,重新建index.jsp页面,因为自动生成的页面缺失指令设置。

    6. 在index.jsp中开发页面,发送请求。

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
      <br><br><br>
      <a href="${pageContext.request.contextPath}/zar/demo.action">访问服务器</a>
      </body>
      </html>
      • /demo 是方法上的注解路径

    7. 在webapp目录上新添目录/admin。

    8. 在/admin目录下新建main.jsp页面,用来进行服务器处理完毕后数据的回显。

    9. 开发DemoAction.java-->控制器(相当于以前的Servlet)。这是一个普通的类,不用继承和实现接口,类中的每个方法就是一个具体的action控制器。

      • 类中的方法定义规范:

        • 访问权限是public

        • 方法名自定义

        • 方法的参数可以有多个,任意类型,用来接收客户端提交上来的数据

        • 方法的返回值任意,以返回String居多

      • @Controller:标识当前类为处理器,交给Spring容器去创建。

      • @RequestMapping:标识路径映射。该注解可以加在类上相当于包名,还可以加在方法上相当于action的名称,都是来指定映射路径的。

      package com.hhb.controller;
      ​
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      ​
      @Controller //交给Spring去创建对象
      @RequestMapping("/zar")
      public class DemoAction {
          /**
           * 以前的Servlet的规范
           * protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {}
           * action中所有的功能实现都是由方法来完成的
           * action方法的规范
           * 1)访问权限是public
           * 2)方法的返回值任意
           * 3)方法名称任意
           * 4)方法可以没有参数,如果有可以是任意类型
           * 5)要使用@RequestMapping注解来声明一个访问的路径(名称)
           */
          @RequestMapping("/demo")
          public String demo() {
              System.out.println("服务器被访问到了");
              return "main";//可以直接跳到/admin/main.jsp
          }
      }

    10. 完成springmvc.xml文件的配置。在工程的类路径即resources目录下创建SpringMVC的配置文件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.hhb.controller"/>
      ​
          <!--添加视图解析器-->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!--配置前缀-->
              <property name="prefix" value="/admin/"/>
              <!--配置后缀-->
              <property name="suffix" value=".jsp"/>
          </bean>
      </beans>
      • SpringMVC框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器InternalResouceViewResolver中引入了请求的前缀与后缀。而action中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。

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

二、SpringMVC注解式开发

2.1@RequestMapping定义请求规则

2.1.1指定模块名称

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

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

示例

提取后

@Controller
@RequestMapping("/zar")
public class HelloSpringMvc {
//相当于一个控制器处理的方法
@RequestMapping("/hello")
public String one() {
return "main";
}
@RequestMapping("/two")
public String two() {
return "main";
}

2.1.2对请求提交方式的定义

  • 对应@RequestMappinp,其中有一个属性method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该method属性指定的提交方式的请求,才会执行该注解方法。

  • method属性的取值为RequestMethod.枚举常量。常用的为RequestMethod.GET与RequestMethod.POST,分别表示提交方式的匹配规则为GET与POST提交。

  • 客户端浏览器常用的请求方式,及其提交方式有以下几种:

post提交方式

get提交方式

2.2五种数据提交的方式

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

2.2.1单个数据注入

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

2.2.2对象封装注入

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

  • get请求不会乱码,post请求会乱码。

2.2.3动态占位符提交(仅用于超链接)

  • 使用框架提供的一个注解@PathVariable,将请求url中的值作为参数进行提取,只能是超链接。

2.2.4请求参数名称与形参名称不一致

  • 请求与形参中的名字不对应,可以使用@RequestParam("name")来进行参数名称绑定。

2.2.5使用HttpServletRequest对象提取

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

2.3请求参数中文乱码解决

  • 对于前面所接收的请求参数,若含有中文并且使用post请求,则会出现中文乱码问题。

  • Spring对于中文请求参数的中文乱码问题,给出了专门的字符集过滤器:spring-web-5.2.5.RELEASE.jar 的org.springframework.web.filter 包下的 CharacterEncodingFilter 类。

2.3.1解决方案

  • 在web.xml中注册字符集过滤器,即可解决Spring的请求参数的中文乱码问题。

  • 最好将该过滤器注册在其它过滤器之前,因为过滤器的执行是按照其注册顺序进行的。

<!--配置中文编码过滤器:解决post请求乱码的问题-->
<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>
    <!--强制request使用字符集encoding-->
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <!--强制response使用字符集encoding-->
    <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>

2.3.2源码分析

2.4处理器方法的返回值

  • 使用@Controller注解的处理器的方法,其返回值常用的有四种类型:

    • ModelAndView

    • String

    • 无返回值void

    • 返回对象类型

2.4.1返回ModelAndView(较少使用)

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

2.4.2返回String

  • 处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。

  • 也可以直接返回资源的物理视图名。不过,此时就需要再在视图解析器中再配置前缀与后缀了。

2.4.3无返回值void

  • 对于处理器方法返回void的应用场景,应用在AJAX响应处理。

  • 若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回void。

  • 代码后面见。

2.4.4返回对象Object

  • 处理器方法也可以返回Object对象。这个Object对象可以是Integer,自定义对象,Map,List等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。

  • 返回对象需要使用@ResponseBody注解,将转换后的JSON数据放入到响应体中。

  • Ajax请求多用于Object返回值类型。

  • 由于转换器底层使用了Jackson转换方式将对象转换为JSON数据,所以需要添加Jackson的相关依赖。

实现步骤

  1. 在pom.xml文件中添加依赖

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>

  2. 添加jQuery的函数库,在webapp目录下新建js目录,拷贝jquery-3.3.1.js到目录下

  3. 发送ajax请求

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <script src="js/jquery-3.3.1.js"></script>
    </head>
    <body>
    <script>
        function show() {
            $.ajax({
                url: "${pageContext.request.contextPath}/ajax.action",
                dataType: "json",
                type: "get",
                success: function (list) {
                    var s = "";
                    $.each(list, function (i, stu) {
                        s += stu.name + "-----" + stu.age + "<br>"
                    });
                    $("#mydiv").html(s);
                }
            })
        }
    </script>
    <a href="javascript:show()">访问服务器</a>
    <div id="mydiv"></div>
    </body>
    </html>

  4. 开发实体类Student

    package com.hhb.pojo;
    ​
    public class Student {
        private String name;
        private int age;
    ​
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    ​
        public String getName() {
            return name;
        }
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public int getAge() {
            return age;
        }
    ​
        public void setAge(int age) {
            this.age = age;
        }
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    ​
        public Student() {
        }
    }

  5. 开发action

    @Controller
    public class AjaxAction {
        @RequestMapping("/ajax")
        //处理ajax请求,一定要加@ResponseBody
        @ResponseBody
        public List<Student> ajax() {
            Student student1 = new Student("张三", 22);
            Student student2 = new Student("李四", 23);
            Student student3 = new Student("王五", 24);
            List<Student> list = new ArrayList<Student>();
            list.add(student1);
            list.add(student2);
            list.add(student3);
            //自动调用json转换工具进行转换
            return list;
        }
    }

  6. 在springmvc.xml文件中添加注解驱动

    <!--添加注解驱动,专门用来处理ajax请求-->
    <mvc:annotation-driven/>

2.5SpringMVC的四种跳转方式

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

  • 可以使用框架提供的关键字redirect:,进行一个重定向操作,包括重定向页面和重定向action。

  • 使用框架提供的关键字forward:,进行服务器内部转发操作,包括转发页面和转发action。

  • 当使用redirect:和forward:关键字时,视图解析器中前缀后缀的拼接就无效了。

页面部分

<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>

Controller部分

 
@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:/fore/user.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:就可以屏蔽前缀和后缀的拼接
    }
}

@Controller
public class OtherAction {
    @RequestMapping("/other")
    public String other(){
        System.out.println("other");
        return "main";
    }
}

2.6SpringMVC支持的默认参数类型

  • 这些类型只要写在方法参数上就可以使用了。

    • HttpServletRequest对象

    • HttpServletResponse对象

    • HttpSession对象

    • Model对象

    • ModelMap对象

    • Map对象

示例

<a href="${pageContext.request.contextPath}/data.action">访问服务器,进行数据携带</a>
@Controller
public class DataAction {
    @RequestMapping("/data")
    public String Data(
            HttpServletRequest request,
            HttpSession session,
            Model model,
            Map map,
            ModelMap modelMap
    ) {
        Users users = new Users("张三", 20);
        request.setAttribute("requestUser", users);
        session.setAttribute("sessionUser", users);
        model.addAttribute("modelUser", users);
        map.put("mapUser", users);
        modelMap.addAttribute("modelMapUser", users);
        //请求转发跳转
        return "main";
        //重定向会丢失数据
        //return "redirect:/admin/main.jsp";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>显示数据</h2>
requestUser:${requestUser}<br>
sessionUser:${sessionUser}<br>
modelUser:${modelUser}<br>
mapUser:${mapUser}<br>
modelMapUser:${modelMapUser}<br>
</body>
</html>
  • 注意:Model、Map、ModelMap都使用的是request请求作用域,意味着只能是请求转发后,页面才可以得到值。

  • response不能携带数据。

2.7日期处理

2.7.1日期注入

在方法的参数上使用@DateTimeFormat注解

  • 日期类型不能自动注入到方法的参数中,需要单独做转换处理,使用@DateTimeFormat注解,需要在springmvc.xml文件中添加mvc:annotation-driven/标签

<form action="${pageContext.request.contextPath}/mydate.action">
    日期:<input type="date" name="dates"><br>
    <input type="submit" value="提交"><br>
</form>
@Controller
public class DateAction {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
​
    @RequestMapping("/mydate")
    public String MyDate(
            @DateTimeFormat(pattern = "yyyy-MM-dd")
            Date dates) {
        System.out.println(dates);
        System.out.println(sdf.format(dates));
        return "show";
    }
}

@InitBinder注解解决类中日期问题

@Controller
public class DateAction {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
​
    //注册一个全局的日期处理注解
    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
    }
​
    @RequestMapping("/mydate")
    public String MyDate(Date dates) {
        System.out.println(dates);
        System.out.println(sdf.format(dates));
        return "show";
    }
}

2.7.2日期显示

JSON中的日期显示

  • 需要在类中的成员变量的getXXX方法上加注解

@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
public Date getDate() {
return date;
}

JSP页面的日期显示

  • 使用JSTL标签库,先添加依赖。

    <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
    </dependency>

  • 导入标签库

    <%--引入jstl核心标签库--%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--%@引入jstl格式化标签库--%>
    <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<a href="${pageContext.request.contextPath}/list.action">显示集合中对象的日期成员</a>
@RequestMapping("/list")
public String listDate(HttpServletRequest request) throws ParseException {
    Student student1 = new Student("张三", sdf.parse("2003-08-19"));
    Student student2 = new Student("李四", sdf.parse("2000-12-09"));
    Student student3 = new Student("王五", sdf.parse("2002-03-29"));
    List<Student> list = new ArrayList<Student>();
    list.add(student1);
    list.add(student2);
    list.add(student3);
    request.setAttribute("list", list);
    return "show";
}
<table width="500px" border="1">
    <tr>
        <th>姓名</th>
        <th>生日</th>
    </tr>
    <c:forEach items="${list}" var="stu">
        <tr>
            <td>${stu.name}</td>
                <%--<td>${stu.birthday}</td>--%>
            <td><fmt:formatDate value="${stu.birthday}" pattern="yyyy-MM-dd"/></td>
        </tr>
    </c:forEach>
</table>

2.8<mvc:annotation-driven/>标签的使用

  • <mvc:annotation-driven/>会自动注册两个bean,分别为DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。是springmvc为@Controller分发请求所必须的。除了注册这两个bean,还提供了很多支持。

    • 支持使用ConversionService实例对表单参数进行类型转换

    • 支持使用@NumberFormat、@DateTimeFormat。

    • 注解完成数据类型的格式化。

    • 支持使用@RequestBody和@ResponseBody注解。

    • 静态资源的分流也使用这个标签。

2.9资源在WEB-INF目录下

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

项目案例

  • 页面结构图:

  • 主要代码:

    package com.hhb.controller;
    ​
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    ​
    import javax.servlet.http.HttpServletRequest;
    ​
    @Controller
    public class WebInfAction {
        @RequestMapping("/showIndex")
        public String ShowIndex() {
            return "index";
        }
    ​
        @RequestMapping("/showMain")
        public String ShowMain() {
            return "main";
        }
    ​
        @RequestMapping("/showLogin")
        public String Login() {
            return "login";
        }
    ​
        @RequestMapping("/login")
        public String doLogin(String name, String pwd, HttpServletRequest request) {
            if ("tom".equals(name) && "123".equals(pwd)) {
                return "main";
            } else {
                request.setAttribute("msg", "用户名或密码错误");
                return "login";
            }
        }
    }
     
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>登录</h2>
<form action="${pageContext.request.contextPath}/login">
    用户名 <input type="text" name="name"><br>
    密码 <input type="password" name="pwd"> ${msg}<br>
    <input type="submit" value="提交">
</form>
</body>
</html>

三、SpringMVC拦截器

  • 拦截器的主要作用是:针对请求和响应进行的额外处理,在请求和响应的过程中添加预处理、后处理和最终处理。

3.1拦截器介绍

3.1.1拦截器的应用场景

  • 日志记录:记录请求信息的日志

  • 权限检查:如登录检查

  • 性能检测:检测方法的执行时间

3.1.2拦截器的执行原理

3.1.3拦截器执行的时机

  • preHandle():预处理,在请求被处理之前进行操作

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

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

3.1.4拦截器实现的两种方式

  • 继承HandlerInterceptorAdapter的父类

  • 实现HandlerInterceptor接口,实现的接口,推荐使用实现接口的方式

3.2自定义拦截器实现权限验证

  • 实现一个权限验证拦截器

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

    <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>

  2. 将所有的页面放入WEB-INF目录下

  3. 开发登录action

    @Controller
    public class WebInfAction {
        @RequestMapping("/showIndex")
        public String ShowIndex() {
            return "index";
        }
    ​
        @RequestMapping("/showMain")
        public String ShowMain() {
            return "main";
        }
    ​
        @RequestMapping("/showLogin")
        public String Login() {
            return "login";
        }
    ​
        //登录业务的判断
        @RequestMapping("/login")
        public String doLogin(String name, String pwd, HttpServletRequest request) {
            if ("tom".equals(name) && "123".equals(pwd)) {
                //在session中存储用户信息,用于进行权限验证
                request.getSession().setAttribute("user", name);
                return "main";
            } else {
                request.setAttribute("msg", "用户名或密码错误");
                return "login";
            }
        }
    }

  4. 开发拦截器

    public class LoginInterceptor implements HandlerInterceptor {
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //判断是否登录
            if (request.getSession().getAttribute("user") == null) {
                request.setAttribute("msg", "您未登录");
                request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
                return false;
            }
            return true;
        }
    }

  5. 配置springmvc.xml文件

    <!--注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--映射要拦截的请求-->
            <mvc:mapping path="/**"/>
            <!--设置放行的请求-->
            <mvc:exclude-mapping path="/showLogin"/>
            <mvc:exclude-mapping path="/login"/>
            <!--配置具体的拦截器实现功能的类 -->
            <bean class="com.hhb.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

四、SSM整合

4.1SSM整合后台功能

(1)新建Maven项目,添加依赖

<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.hhb</groupId>
  <artifactId>SpringMVC006-ssm</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SpringMVC006-ssm Maven Webapp</name>
​
  <!-- 集中定义依赖版本号 -->
  <properties>
    <junit.version>4.12</junit.version>
    <spring.version>5.2.5.RELEASE</spring.version>
    <mybatis.version>3.5.1</mybatis.version>
    <mybatis.spring.version>1.3.1</mybatis.spring.version>
    <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
    <mysql.version>5.1.32</mysql.version>
    <slf4j.version>1.6.4</slf4j.version>
    <druid.version>1.1.12</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>
    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</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>5.2.5.RELEASE</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>
​
    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</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>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <scope>provided</scope>
      <version>${jsp-api.version}</version>
    </dependency>
    <!-- Jackson Json处理工具包 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
      <version>20140107</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>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <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>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>
</project>

(2)拷贝所有的配置文件到config,开发每个配置文件

jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmuser
jdbc.username=root
jdbc.password=030522

mybatis-config.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>
</configuration>

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 https://www.springframework.org/schema/context/spring-context.xsd">
​
    <!--引入外部的属性配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
​
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
​
    <!--配置SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--指定mybatis核心配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--注册实体类-->
        <property name="typeAliasesPackage" value="com.hhb.pojo"/>
    </bean>
​
    <!--Mapper扫描配置器,主要扫描Mapper接口,生成代理类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hhb.mapper"/>
    </bean>
​
</beans>

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"
       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:property-placeholder location="classpath:jdbc.properties"/>
​
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
​
    <!--配置SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--指定mybatis核心配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--注册实体类-->
        <property name="typeAliasesPackage" value="com.hhb.pojo"/>
    </bean>
​
    <!--Mapper扫描配置器,主要扫描Mapper接口,生成代理类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hhb.mapper"/>
    </bean>
​
</beans>

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"
       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.hhb.controller"/>
​
    <!--添加注解驱动-->
    <mvc:annotation-driven/>
    
    <!--因为本项目全部是ajax请求,不需要配置视图解析器-->
</beans>

(3)在web.xml文件中完成springmvc,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">
    <!--添加中文编码过滤器
    private String encoding;
    private boolean forceRequestEncoding;
    private boolean forceResponseEncoding;-->
    <filter>
        <filter-name>encode</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <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>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
​
    <!--注册Spring框架,目的是启动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>

(4)创建实体类对象User

package com.hhb.pojo;
​
public class User {
    private String userId;
    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 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;
    }
​
    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 User() {
    }
}

(5)创建UserMapper接口和实现功能的UserMapper.xml

UserMapper

package com.hhb.mapper;
​
import com.hhb.pojo.User;
import org.apache.ibatis.annotations.Param;
​
import java.util.List;
​
public interface UserMapper {
    //根据条件分页获取分页数据
    List<User> selectUserPage(
            @Param("userName")
            String userName,
            @Param("userSex")
            String userSex,
            @Param("startRow")
            int startRow);
​
    //增加用户
    int createUser(User user);
​
    //根据用户ID删除用户
    int deleteUserById(String userId);
​
    //获取总行数
    int getRowCount(
            @Param("userName")
            String userName,
            @Param("userSex")
            String userSex
    );
}

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.hhb.mapper.UserMapper">
    <!--完成实体类与表中列名的映射-->
    <resultMap id="userMap" type="user">
        <id property="userId" column="user_id"/>
        <result property="cardType" column="card_type"/>
        <result property="cardNo" column="card_no"/>
        <result property="userName" column="user_name"/>
        <result property="userSex" column="user_sex"/>
        <result property="userAge" column="user_age"/>
        <result property="userRole" column="user_role"/>
    </resultMap>
    <!--定义全部列名-->
    <sql id="allColumns">
        user_id
        ,card_type,card_no,user_name,user_sex,user_age,user_role
    </sql>
    <!--根据条件分页获取分页数据-->
    <select id="selectUserPage" resultMap="userMap">
        select
        <include refid="allColumns"></include>
        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>
        limit #{startRow},5
    </select>
​
    <!--增加用户-->
    <insert id="createUser" parameterType="user">
        insert into user
        values (#{userId}, #{cardType}, #{cardNo}, #{userName}, #{userSex}, #{userAge}, #{userRole})
    </insert>
​
    <!--根据用户ID删除用户-->
    <delete id="deleteUserById" parameterType="String">
        delete
        from user
        where user_id = #{userId}
    </delete>
​
    <!--获取总行数-->
    <select id="getRowCount" resultType="int" parameterType="String">
        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>
</mapper>

(6)创建业务逻辑层UserService接口和实现类

UserService

package com.hhb.service;
​
import com.hhb.pojo.User;
import org.apache.ibatis.annotations.Param;
​
import java.util.List;
​
public interface UserService {
    //根据条件分页获取分页数据
    List<User> selectUserPage(String userName, String userSex, int startRow);
​
    //增加用户
    int createUser(User user);
​
    //根据用户ID删除用户
    int deleteUserById(String userId);
​
    //获取总行数
    int getRowCount(String userName, String userSex);
}

UserServiceImpl

package com.hhb.service.impl;
​
import com.hhb.mapper.UserMapper;
import com.hhb.pojo.User;
import com.hhb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.List;
​
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
​
    @Override
    public List<User> selectUserPage(String userName, String userSex, int startRow) {
        return userMapper.selectUserPage(userName, userSex, startRow);
    }
​
    @Override
    public int createUser(User user) {
        return userMapper.createUser(user);
    }
​
    @Override
    public int deleteUserById(String userId) {
        return userMapper.deleteUserById(userId);
    }
​
    @Override
    public int getRowCount(String userName, String userSex) {
        return userMapper.getRowCount(userName, userSex);
    }
}

(7)创建测试类进行功能测试

package test;

import com.hhb.pojo.User;
import com.hhb.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.List;

//启动spring容器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext_mapper.xml", "classpath:applicationContext_service.xml"})
public class ServiceTest {
    @Autowired
    private UserService userService;

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

    @Test
    public void testCreateUser() {
        User user = new User("15968162087363061", "身份证", "114264195202156468", "赵云", "男", "29", "打野");
        int count = userService.createUser(user);
        System.out.println(count);
    }

    @Test
    public void testDeleteUserById(){
        int count = userService.deleteUserById("15968162087363060");
        System.out.println(count);
    }

    @Test
    public void test(){
        int rowCount = userService.getRowCount(null, null);
        System.out.println(rowCount);
    }
}

(8)创建action进行分页显示,查询用户个数,删除处理

package com.hhb.controller;
​
import com.hhb.pojo.User;
import com.hhb.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.List;
​
@CrossOrigin
@RestController //如果本类中全部都是ajax请求,则使用此注解,方法上的@ResponseBody可以省略
@RequestMapping("/user")
public class UserController {
    //切记:一定要有业务逻辑层对象
    @Autowired
    private UserService userService;
​
    public static final int PAGE_SIZE = 5;
​
    @RequestMapping("/selectUserPage")
    public List<User> selectUserPage(String userName, String userSex, Integer page) {
        //根据页面计算起始行
        int startRow = 0;
        if (page != null) {
            startRow = (page - 1) * PAGE_SIZE;
        }
        return userService.selectUserPage(userName, userSex, startRow);
    }
​
    @RequestMapping("/getRowCount")
    public int getRowCount(String userName, String userSex) {
        return userService.getRowCount(userName, userSex);
    }
​
    @RequestMapping("/createUser")
    public int createUser(User user) {
        String userId = System.currentTimeMillis() + "";
        user.setUserId(userId);
        return userService.createUser(user);
    }
​
    @RequestMapping("/deleteUserById")
    public int deleteUserById(String userId) {
        return userService.deleteUserById(userId);
    }
}

4.2Vue实现前台功能

(1)安装node.js

  • 查看版本编号

    node -v
    npm -v

  • node.js的安装是为了使当前的计算机使用vue的框架,预安装的工具。

  • 类似于运行java程序必须按照JDK一样的道理。

(2)构建项目

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

cd E:\idea_workspace\vuedemo01 进入到当前项目的目录下
​
npm i element -ui -S 下载elementUI的框架
​
npm install //打包项目
​
npm install --save vue-axios //下载跨域访问组件axios

(3)为idea添加vue插件

(4)配置启动项

(5)项目结构

 
​​​​​​​build   项目构建(webpack)相关代码
config  配置目录,包括端口号等。我们初学可以使用默认的。
node_modules    npm 加载的项目依赖模块
src     
这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:
    assets: 放置一些图片,如logo等。
    components: 目录里面放了一个组件文件,可以不用。
    App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。
    main.js: 项目的核心文件。
​
static  静态资源目录,如图片、字体等。
test    初始测试目录,可删除
.xxxx文件     这些是一些配置文件,包括语法配置,git配置等。
index.html  首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
package.json    项目配置文件。
README.md   项目的说明文档,markdown 格式

(6)UserHome.vue解读

  • UserHome.vue是所有功能实现的组件.与后台跨域访问,分页显示数据,并实现增加,按主键删除,批量删除,更新,多条件查询等功能.

  • 首先确定钩子函数中的启动访问函数

    created() {
            this.handlePageChange();           ===>分页
            this.getRowCount();                ===>计算总行数
          }

  • 分页函数解析

    handlePageChange() {
             //定义变量,封装将要提交的数据
             let postData=this.qs.stringify({
                page:this.currentPage,
                userName:this.formInline.search1,
                userSex:this.formInline.search2
              });
              this.$axios({                    ==>发出跨域访问的请求,参考$.ajax();
                method:'post',                 ==>请求提交的方式
                url:'/api/user/selectUserPage',==>服务器的地址
                data:postData  //this.qs.stringify==>{"page":1,"userName":"","userSex":""}                               ==>提交的数据
              }).then(response=>{              ==>成功后进入到这里
                this.tableData=response.data;  ==>数据绑定,返回的5个用户的json数据,一下子绑定给表格
              }).catch(error=>{                ==>出错了进入到这里
                console.log(error);
              })
            }

  • 计算总行数函数分析

     getRowCount() {
              //创建变量,提取文本框和下拉列表框中的数据
              let postData=this.qs.stringify({
                userName:this.formInline.search1,
                userSex:this.formInline.search2
              });
              this.$axios({                  ==>发出跨域访问的请求,参考$.ajax();
                method:'post',               ==>请求提交的方式
                url:'/api/user/getRowCount', ==>服务器的地址
                data:postData                ===>提交的数据
              }).then(response=>{
                this.total=response.data;    ==>返回的总行数赋值给变量total
              }).catch(error=>{
                console.log(error);
              })
            },

  • 按主键删除分析

     //弹出提示框,让用户确定是否删除 
          this.$confirm('删除操作, 是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'                      ==>黄色的警告图标
          }).then(() => {                        ==>用户点击确定后进入到这里
            let postData = this.qs.stringify({   ==>封装成JSON数据格式
              userId: row.userId,                ==>将要提交的主键值
            });
            this.$axios({                      ==>发出跨域访问的请求,参考$.ajax();
              method: 'post',                    ==>请求提交的方式
              url: '/api/user/deleteUserById',
              data: postData  //{"userId":15968162893439470}
            }).then(response => {                ==>跨域请求成功后进入这里
              this.getRowCount();     ==>计算删除后的总行数,进行分页插件的页码变化
              ...
              this.handlePageChange();            ==>删除后重新分页
              this.$message({                     ==>删除成功后弹框
                type: 'success',
                message: '删除成功!'
              });          
            }).catch(error => {
              console.log(error);
            });
    ​
          }).catch(() => {                        ===>用户点击取消后进入到这里
            this.$message({
              type: 'info',
              message: '已取消删除'
            });
          });
        },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/825877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

好用的低代码开发平台是什么样的?

一、好用的低代码开发平台是什么样的&#xff1f; 从企业角度来说&#xff0c;优化流程&#xff0c;提升企业运行效率&#xff1b;节省成本&#xff0c;提高企业效益&#xff1b;维护方便&#xff0c;即改即用&#xff1b;一键升级&#xff0c;方便实用&#xff1b; 从开发者角…

JVM | 从类加载到JVM内存结构

引言 我在上篇文章&#xff1a;JVM | 基于类加载的一次完全实践 中为你讲解如何请“建筑工人”来做一些定制化的工作。但是&#xff0c;大型的Java应用程序时&#xff0c;材料&#xff08;类&#xff09;何止数万&#xff0c;我们直接堆放在工地上&#xff08;JVM&#xff09;…

企业如何有效保护文件传输的安全性

文件传输是现代商业世界中每个企业日常操作的必需品。但是&#xff0c;传统的文件传输方式&#xff0c;如电子邮件和网络共享&#xff0c;并不总是安全可靠。黑客攻击、网络钓鱼和数据泄露等风险时刻存在。因此&#xff0c;企业需要采取措施保障文件传输的安全性。本文将介绍如…

Shell脚本学习-case条件语句

case条件语句相当于多分支的if/elif/else条件语句&#xff0c;但是它更规范工整。常被应用于实现系统服务启动脚本等企业应用场景中。 语法结构&#xff1a; case "变量" in值1)指令1...;;值2)指令2...;;*)指令3... esac 说明&#xff1a; 1&#xff09;case语句…

从 GPU 到 ChatGPT,一文带你理清GPU/CPU/AI/NLP/GPT之间的千丝万缕【建议收藏】

目录 硬件 GPU 什么是 GPU&#xff1f; GPU 是如何工作的&#xff1f; GPU 和 CPU 的区别 GPU 厂商 海外头部 GPU 厂商&#xff1a; 国内 GPU 厂商&#xff1a; nvidia 的产品矩阵 AI 什么是人工智能 (Artificial Intelligence-AI)&#xff1f; 人工智能细分领域 …

手把手教你写代码——基于控制台的通讯录管理系统(多人)(代码详细注释)

写在前面 本文章适合刚开始学习java的同学&#xff0c;不适合已参与java开发的人群&#xff01;本项目源代码已绑定资源中可免费获取&#xff01;如果对你有帮助请 栏目介绍 本栏目专为入门java学习者设计的一些简单的入门项目 功能介绍 本项目为简单的基于控制台的通讯录管理系…

音乐节《迷笛音乐节》游玩感

上周&#xff0c;去了烟台&#xff0c;参加音乐节&#xff0c;以前从未参加过&#xff0c;所以趁着本周六周日双休的时候&#xff0c;去游玩了一次。&#xff08;1&#xff09;一种新奇体验 对于自己来说&#xff0c;参加音乐节还是一种新奇的体验的&#xff0c;也是疫情放开了…

【MyBatis】初学MyBatis

目录 MyBatis 是什么&#xff1f;MyBatis框架搭建1.添加MyBatis框架2.设置MyBatis配置数据库的相关链接信息xml 保存路径和命名格式 根据MyBatis写法完成数据库的操作MyBatis插件MyBatis传递参数查询${} 和 #{} 有什么区别&#xff1f;SQL注入问题 MyBatis like查询MyBatis多表…

Lombok,一个神奇的存在

1、概述 Lombok主要用于在编译POJO类源文件时通过注解的方式自动为该类生成构造方法、getter/setter、equals、hashcode、toString等方法&#xff0c;有效地简化了POJO类代码&#xff0c;提高了软件的开发速度。 2、安装 a、启动IntelliJ IDEA—>点击CtrlAltS快捷键&…

【LeetCode】链表反转

题目 题目&#xff1a;给定单链表头节点&#xff0c;将单链表的链接顺序反转过来 例&#xff1a; 输入&#xff1a;1->2->3->4->5 输出&#xff1a;5->4->3->2->1 要求&#xff1a;按照两种方式实现 解决办法 方式一&#xff1a;&#xff08;直接迭…

从0开始自学网络安全(黑客)

前言 黑客技能是一项非常复杂和专业的技能&#xff0c;需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤&#xff0c;系统自学网络安全。 在学习之前&#xff0c;要给自己定一个目标或者思考一下要达到一个什么样的水平&#xff0c;是学完找工作&#xff08;…

这所211考数一英二,学硕降分33分,十分罕见!

一、学校及专业介绍 合肥工业大学&#xff08;Hefei University of Technology&#xff09;&#xff0c;简称“合工大”&#xff0c;校本部位于安徽省合肥市&#xff0c;是中华人民共和国教育部直属的全国重点大学&#xff0c;是国家“双一流”建设高校&#xff0c; 国家“211工…

PHP代码审计——实操!

ctfshow PHP特性 web93 八进制与小数点 <?php include("flag.php"); highlight_file(__FILE__); if(isset($_GET[num])){$num $_GET[num];if($num4476){die("no no no!");}if(preg_match("/[a-z]/i", $num)){die("no no no!")…

git 忽略掉不需要的文件

第一步&#xff1a;创建.gitignore文件 touch .gitignore 第二步&#xff1a;使用vi编辑器 输入不需要的文件&#xff0c;或用通配符*来忽视一系列文件 效果&#xff1a;

【Java可执行命令】(十二)依赖分析工具jdeps:通过静态分析字节码并提取相关信息来实现依赖分析 ~

Java可执行命令之jdeps 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 jdeps -dotoutput < dir>3.3 jdeps -s3.4 jdeps -v3.5 jdeps -cp < path>3.6 注意事项&#xff1a; 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 Java中的jdeps命令是一个用于分析类…

使用脱机 MFA确保远程员工的安全

远程工作支持的优势 未更改的企业访问&#xff1a;远程工作支持开辟了访问企业网络和资源以及其中保存的数据的替代方法。应采取必要措施&#xff0c;确保它们保持完整&#xff0c;不受远程破坏企图的影响。提高工作效率&#xff1a;理想情况下&#xff0c;远程工作支持可提高…

程序框架-事件中心模块-观察者模式

1.Monster //触发事件 EventCenter.GetInstance().EventTrigger("MonsterDead",this);2.Player void Start() { EventCenter.GetInstance().AddEventListener("MonsterDead", MonsterDeadDo); }public void MonsterDeadDo(object info) {Debug.Log(&q…

【测试开发】Mq消息重复如何测试?

本篇文章主要讲述重复消费的原因&#xff0c;以及如何去测试这个场景&#xff0c;最后也会告诉大家&#xff0c;目前互联网项目关于如何避免重复消费的解决方案。 Mq为什么会有重复消费的问题? Mq 常见的缺点之一就是消息重复消费问题&#xff0c;产生这种问题的原因是什么呢…

从封面开始,打造一个引人注目的视频作品

在如今的互联网时代&#xff0c;短视频已经成为了人们生活中不可或缺的一部分。而一个吸引人的视频封面可以让你的作品更具吸引力&#xff0c;吸引更多观众的点击。那么&#xff0c;如何制作一个令人印象深刻的视频封面呢&#xff1f;下面就让我们揭秘一些实用技巧吧&#xff0…

Chrome 75不支持保存成mhtml的解决方法

在Chrome 75之前&#xff0c;可以设置chrome://flags -> save as mhtml来保存网页为mhtml。 升级新版&#xff0c;发现无法另存为/保存网页为MHTML了。 在网上搜索无果后&#xff0c;只得从chromium项目的commits中查找&#xff0c;原来chrome搞了个"Chrome Flag Owner…