二、Spring MVC 进阶

本文详细介绍了Spring MVC中如何使用Ajax进行异步交互,包括如何配置和使用Jackson库进行JSON数据转换,以及@RequestBody和@ResponseBody注解的用途。接着,文章阐述了RESTful风格的HTTP请求方法,并展示了如何在Spring MVC中实现RESTful API。此外,还讲解了文件上传的原理和在Spring MVC中配置文件上传解析器的方法,以及单文件和多文件上传的示例。最后,讨论了Spring MVC的异常处理机制,包括自定义异常处理器和Web层的错误页面配置,以及拦截器的使用和拦截器链的概念。

一、Ajax异步交互传递json格式的数据

Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入jackson的包;同时使用 <mvc:annotation-driven />这个注解实现其他数据和json数据之间的转换。

<!--Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入
jackson的包;同时使用 <mvc:annotation-driven />-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
       <!--显示配置处理器映射器和处理器适配器-->
    <!--
        在开发中经常使用这个标签显示的配置处理器映射器和处理器适配器,
        配置了这个标签之后,还增强了功能,支持json字符串的读写(不需要使用json的API了)
    -->
    <mvc:annotation-driven/>
</beans>

1.@RequestBody & @ResponseBody

@RequestBody: 该注解用于Controller的方法的形参声明,当使用ajax提交并指定contentType为json形式时,通过HttpMessageConverter接口将json数据转换为对应的POJO对象。
@ResponseBody: 该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
ajax.jsp

<%--
  Created by IntelliJ IDEA.
  User: ASUS
  Date: 2021/10/22
  Time: 10:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>ajax异步请求传输json数据格式的字符串</title>
</head>
<body>
<%--在网络传输中数据的格式有json、xml格式的。json比较流行--%>
<%--1.导入jQuery包,利用api发送ajax请求--%>
<script src="${pageContext.request.contextPath}/js/jquery-3.5.1.js"></script>

<%--2.按钮dom对象--%>
<button id="btn1">发送ajax异步请求,传递集合类型的json数据</button>
<button id="btn2">发送ajax异步请求,传递pojo类型的json数据</button>

<%--3.编写js代码,发送ajax异步请求--%>
<script type="text/javascript">
    // 3.1获取按钮对象,绑定单击事件
    $("#btn1").click(function () {
        let url = '${pageContext.request.contextPath}/user/ajaxRequestList';
        let data = '[{"id":1,"name":"张三"},{"id":2,"name":"李四"}]';
        $.ajax({
            type: 'POST',
            url: url,
            data: data,
            contentType: 'application/json;charset=utf-8',
            success: function (resp) {
                console.log(resp);
                alert(JSON.stringify(resp));
            }
        })
    });

    // 3.2获取按钮对象,绑定单击事件
    $("#btn2").click(function () {
        let url = '${pageContext.request.contextPath}/user/ajaxRequestPojo';
        let data = '{"id":1,"name":"徐国文"}';
        $.ajax({
            type: 'POST',
            url: url,
            data: data,
            contentType: 'application/json;charset=utf-8',
            success: function (resp) {
                console.log(resp);
                alert(JSON.stringify(resp));
            }
        })
    })

</script>
</body>
</html>

Controller

@Controller // 将创建的UserController对象存储到Spring MVC创建的ioc容器中(子容器)
@RequestMapping("/user")    // 一级访问目录
public class UserController {
/**
     * 将前端页面传递的json数据转换为java对象,借助@RequestBody
     * Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换
     * @param list
     */
    @RequestMapping(value = "/ajaxRequestList",method = RequestMethod.POST)
    @ResponseBody
    public List<User> ajaxRequestList(@RequestBody List<User> list) {
        System.out.println(list);
        return list;
    }

    /**
     * 前端页面传递对象格式的json数据,然后将json数据自动封装到User实体类对象上,
     * 并且将实体类user转换为json数据
     * @param user
     * @return
     */
    @RequestMapping("/ajaxRequestPojo")
    @ResponseBody
    public User ajaxRequestPojo(@RequestBody User user) {
        System.out.println(user);
        return user;
    }
}

二、Restful风格

1.什么是RESTful?

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用 “url+请求方式” 表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:

  • GET:读取(Read)
  • POST:新建(Create)
  • PUT:更新(Update)
  • DELETE:删除(Delete)
客户端请求原来风格URL地址RESTful风格URL地址
查询所有/user/findAllGET /user
根据id查询/user/findByIdGET /user/1
新增/user/savePOST /user
修改/user/updatePUT /user/1
删除/user/deleteDELETE /user/1

2.代码实现

  • @PathVariable 用来接收RESTful风格请求地址中占位符的值
  • @RestController RESTful风格多用于前后端分离项目开发,前端通ajax与服务器进行异步交互,我们处理器通常返回的是json数据所以使用@RestController来替代@Controller和@ResponseBody两个注解。
  • @GetMapping/@PostMapping/@PutMapping/@DeleteMapping 这四个注解替代了@RequestMapping注解。@GetMapping("/user/{id}")就相当于@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
import cn.xuguowen.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * @author 徐国文
 * @create 2021-10-22 18:22
 */
// @Controller
@RestController // 组合注解:相当于@Controller + @ResponseBody 两个注解的功能
@RequestMapping("/restful")     // 一级访问路径
public class RestfulController {
    /**
     * 模拟查询所有用户信息
     * 传统开发要想访问到这个方法,需要编写的请求路径是:localhost:8080/项目名称/restful/user?id=2
     * 现在使用Restful风格,请求路径是:localhost:8080/项目名称/restful/user/2 + 请求方式
     * @return
     */
    // {id}是Restful中的占位符。请求路径和请求方式组合起来就是根据id查询用户的功能
    // @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    @GetMapping("/user/{id}")
    // @ResponseBody
    public String findById(@PathVariable  Integer id) {
        // 实际开发中,要调用业务层的的查询方法,将获取到的id值传递
        // 那么问题来了:如何获取到参数id的值并且将赋值给形参中的id呢?
        // 解决问题:使用注解@PathVariable将参数id值赋值给形参id

        // 问题二:这样写返回值,框架会认为是字符串逻辑视图名称,那么视图解析器会拼接前缀和后缀,这样的话就会出现404的错误
        // 如何解决这个问题呢?使用@ResponseBody注解,就不会经过视图解析器了,就是将字符串内容写在了页面上
        return "findById:" + id;
    }

    /**
     * 使用Restful风格编写查询所有用户信息
     * @return
     */
    // 原始请求url:localhost:8080/项目名称/restful/user
    // Restful请求方式:localhost:8080/项目名称/restful/user + 请求方式
    // @RequestMapping(value = "/user",method = RequestMethod.GET)
    @GetMapping("/user")
    // @ResponseBody
    public String findAll() {
        return "findAll";
    }

    /**
     * Restful风格下插入用户信息
     * 将表单中的数据都封装到user对象中
     * @param user
     * @return
     */
    // @RequestMapping(value = "/user",method = RequestMethod.POST)
    @PostMapping("/user")
    // @ResponseBody
    public String insert(User user) {
        System.out.println(user);
        return "insert";
    }

    // 修改(put)和删除(delete)用户信息的测试可以在postman软件中测试

    /**
     * Restful风格下实现根据id修改用户信息
     * @return
     */
    // @RequestMapping(value = "/user/1",method = RequestMethod.PUT)
    @PutMapping("/user/{id}")
    // @ResponseBody
    public String update(@PathVariable Integer id) {
        System.out.println("用户的id是:" + id);
        return "update";
    }

    /**
     * Restful风格下根据用户id删除用户信息
     * @return
     */
    // @RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
    @DeleteMapping("/user/{id}")
    // @ResponseBody
    public String delete(@PathVariable Integer id) {
        System.out.println("用户的id值为 " + id);
        return "delete";
    }
}


三、文件上传

1.文件上传的三要素

  • 表单项 type=“file”
  • 表单的提交方式 Method=“POST”
  • 表单的enctype属性是多部件表单形式 enctype=“multipart/form-data”

2.文件上传原理

  • 当form表单的enctype取值为application/x-www-form-urlencoded时,form表单的正文内容格式是:name=value&name=value键值对。在这种情况下,使用request.getParameter()是可以根据表单项name的属性值获取到表单项的value值
  • 当form表单的enctype取值为mutilpart/form-data时,请求正文内容就变成多部件表单形式
    在这里插入图片描述

3.单文件上传

导入fileupload和io依赖坐标

 <!--导入文件上传需要的依赖坐标-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

在Spring mvc的核心配置文件中配置文件上传解析器

 <!--
        1.配置文件上传解析器对象
            当提交表单后,文件会先经过文件上传解析器进行解析,解析完毕之后封装为MultipartFile对象,
            这个对象中存储着文件的信息,可以调用它的方法完成文件的上传
    -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--可以对此文件解析器配置一些属性-->
        <!--设置文件上传的最大值为5MB 5 * 1024 * 1024-->
        <property name="maxUploadSize" value="5242880"/>
        <!--设置文件上传时写入内存的最大值,如果小于这个value值就不会创建临时文件,默认值时10240-->
        <property name="maxInMemorySize" value="40960"/>
    </bean>

fileUpload.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试文件上传</title>
</head>
<body>
<%--
    1.请求方式为post
    2.表单为多部件上传表单enctype="multipart/form-data"
    3.必须存在type="file" 的表单项
--%>
<form action="${pageContext.request.contextPath}/fileUpload" method="post" enctype="multipart/form-data">
    名称: <input type="text" name="username"> <br>
    上传文件: <input type="file" name="filePic"> <br>
    <input type="submit" value="单文件上传">
</form>
<br>
</body>
</html>

FileUploadController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;


/**
 * @author 徐国文
 * @create 2021-10-22 21:46
 */
@Controller
public class FileUploadController {
    /**
     * 实现单文件上传
     * 需要注意的是:表单中name的值一定要和controller中的业务方法的形参名称相同,这样框架才会帮助我们完成封装
     * @param username
     * @param filePic 就是通过文件上传解析器解析之后的文件对象
     * @return
     */
    @RequestMapping("/fileUpload")
    public String fileUpload(String username, MultipartFile filePic) {
        System.out.println("名称:" + username);
        // System.out.println(filePic);
        try {
            // 获取文件的原始名称来充当上传后的文件名称
            String originalFilename = filePic.getOriginalFilename();
            // 1.实现文件的上传
            filePic.transferTo(new File("D:/xxx/" + originalFilename));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 文件上传成功 跳转到success.jsp页面上,视图解析器会为逻辑视图拼接上前缀和后缀的
        return "success";
    }
}


4.多文件上传

fileUpload.jsp

<%--多文件上传--%>
<form action="${pageContext.request.contextPath}/filesUpload" method="post" enctype="multipart/form-data">
    名称: <input type="text" name="username"> <br>
    上传文件: <input type="file" name="filePic"> <br>
    <input type="file" name="filePic"> <br>
    <input type="submit" value="多文件上传">
</form>

FilesUploadController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * @author 徐国文
 * @create 2021-10-22 22:41
 */
@Controller
public class FilesUploadController {
    /**
     * 多文件上传:文件上传解析器解析多个文件,将后将这多个文件对象封装为MultipartFile[]数组对象
     * @param username
     * @param filePic
     * @return
     */
    @RequestMapping("/filesUpload")
    public String filesUplodad(String username, MultipartFile[] filePic) {
        System.out.println(username);

        // 遍历数组。获取到每个文件对象,单独操作
        for (MultipartFile multipartFile : filePic) {
            try {
                // 获取原始的文件名称
                String originalFilename = multipartFile.getOriginalFilename();
                // 将文件上传到本地磁盘中
                multipartFile.transferTo(new File("D:/xxx/" + originalFilename));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }
}


四、异常处理

1.在Java中,对于异常的处理一般有两种方式:

  • 一种是当前方法捕获处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合。
  • 另一种是自己不处理,而是抛给调用者处理(throws),调用者再抛给它的调用者,也就是一直向上抛。在这种方法的基础上,衍生出了SpringMVC的异常处理机制。
  • 系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
    在这里插入图片描述

2.自定义异常处理器

①:创建异常处理器类实现HandlerExceptionResolver接口

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 徐国文
 * @create 2021-10-23 11:53
 * 自定义异常类的实现步骤
 *  1.定义自定义异常类
 *  2.在mvc核心配置文件中配置自定义异常类实例对象:xml方式 / 注解方式
 *  3.编写错误页面:就是出现异常要跳转的页面
 *  4.测试异常跳转:请求/testException这个业务方法实现测试效果
 */
public class GlobalExceptionResolver implements HandlerExceptionResolver {
    /**
     * 当出现异常时,会执行这个方法
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e 实际抛出的异常对象
     * @return
     */
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error",e.getMessage());
        // 逻辑视图名称:会经过视图解析器进行前缀和后缀的拼接
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

②:在mvc的核心配置文件中配置异常处理器(生成实例化对象)

    <bean id="globalExceptionResolver" class="cn.xuguowen.exception.GlobalExceptionResolver"></bean>
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
}

③:编写异常页面 error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>错误页面</title>
</head>
<body>
<h1>这是一个全局异常页面!</h1>
${error}
</body>
</html>

④:测试异常跳转

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author 徐国文
 * @create 2021-10-23 11:45
 * 测试自定义异常类
 */
@Controller
public class TestExceptionController {
    /**
     * 如果没有编写实现HanderExceptionResolver接口的实现类,那就会使用mvc框架提供的实现类,为我们处理异常
     * 但是:实际开发中:异常处理我们需要自定义。因为异常的种类有很多种
     * 所以就需要自定义异常类实现HanderExceptionResolver异常处理器这个接口
     * @return
     */
    @RequestMapping("/testException")
    public String testException() {
        int i = 1 / 0;
        // 逻辑视图:拼接前缀和后缀
        return "success";
    }
}

3.Web异常处理机制

web.xml

<!--响应状态码为500应该展现的页面-->
    <error-page>
        <error-code>500</error-code>
        <location>/500.jsp</location>
    </error-page>
    <!--响应状态码为404应该展现的页面-->
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>

500.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
服务器端错误,请您稍后重试!
</body>
</html>

404.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
宝,您请求的资源不存在!
</body>
</html>


五、拦截器

1.拦截器(interceptor)的作用

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器中的方法进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

2.拦截器和过滤器的区别

区别过滤器拦截器
使用范围是Servlet规范中的一部分,任何 Java Web工程都可以使用是Spring MVC框架自己的,只有使用了Spring MVC框架的工程才可以使用
拦截范围在url-pattern中配置了/*之后,可以对所有要访问的资源进行过滤只会拦截要访问的控制器中的方法,如果访问的是jsp、html、css、image、js 是不会进行拦截的

3.快速入门

①:创建拦截器类实现HandlerInterceptor接口

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 徐国文
 * @create 2021-10-23 14:15
 * 1.Spring MVC中的拦截器类似于java web中的过滤器Filter,用于对处理器(Controller)进行预处理和后处理
 * 2.但是他俩也不是完全的一样,还是有差别的。(面试题)
 *      ①使用范围:拦截器 interceptor是Spring mvc框架自己的,只有使用了Spring mvc框架的工程才可以使用
 *               过滤器是servlet规范中的一部分,任何的java web工程都可以使用
 *      ②拦截范围:拦截器只会拦截你要访问的控制器中的方法,如果访问的是jsp,html,css,image,js 是不会被拦截的
 *                过滤器在url-pattern中配置上 /*之后,可以对所有要访问的资源进行拦截
 * 3.Spring mvc中的拦截器也是AOP思想的具体体现:在不改变controller中的方法的前提下,对方法进行增强
 * 4.HandlerInterceptor拦截器接口,该接口中提供了3个默认方法(jdk9)
 */
public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * 在执行目标方法之前执行
     * @param request
     * @param response
     * @param handler
     * @return false:表示不放行 true:表示放行
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle1执行了!");
        // 放行
        return true;
    }

    /**
     * 在目标方法执行之后,视图对象返回之前 执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle1执行了!");
    }

    /**
     * 在流程都完毕之后 执行(这一整次的请求和响应执行完毕之后执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion1执行了!");
    }
}

②:在mvc核心配置文件中配置拦截器链

<!--配置拦截器链 当配置了多个拦截器后,要注意拦截器的执行顺序-->
    <mvc:interceptors>
        <!--自定义拦截器一-->
        <mvc:interceptor>
            <!--拦截路径配置-->
            <mvc:mapping path="/**"/> <!--表示对所有请求controller中的方法都进行拦截-->
            <!--自定义拦截器类-->
            <bean class="cn.xuguowen.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>

③:测试拦截器的拦截效果(关注点是每个方法的执行顺序)

编写Controller,发请求到controller,跳转页面

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author 徐国文
 * @create 2021-10-23 14:31
 * 目标controller 控制器
 */
@Controller
public class TargetController {
    /**
     * 目标方法:对该方法进行拦截
     * @return
     */
    @RequestMapping("/targetMethod")
    public String targetMethod() {
        System.out.println("targetMethod目标方法执行了!");
        return "success";
    }
}

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--el表达式获取request域中存储的数据--%>
<h1>Success...${username}</h1>

<%
    System.out.println("视图跳转渲染完成,整个流程执行完毕了!");
%>
</body>
</html>


4.拦截器链

开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链。开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序(postHandle()和afterCompletion()两个方法的执行顺序和拦截器配置的顺序相反)。
自定义拦截器2

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 徐国文
 * @create 2021-10-23 14:15
 * 自定义拦截器2
 */
public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 在执行目标方法之前执行
     * @param request
     * @param response
     * @param handler
     * @return false:表示不放行 true:表示放行
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2执行了!");
        // 放行
        return true;
    }

    /**
     * 在目标方法执行之后,视图对象返回之前 执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2执行了!");
    }

    /**
     * 在流程都完毕之后 执行(这一整次的请求和响应执行完毕之后执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2执行了!");
    }
}

配置拦截器链

<!--配置拦截器链 当配置了多个拦截器后,要注意拦截器的执行顺序-->
    <mvc:interceptors>
        <!--自定义拦截器一-->
        <mvc:interceptor>
            <!--拦截路径配置-->
            <mvc:mapping path="/**"/> <!--表示对所有请求controller中的方法都进行拦截-->
            <!--自定义拦截器类-->
            <bean class="cn.xuguowen.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.xuguowen.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

5.拦截器中方法的介绍

方法名说明
preHandle()该方法将在请求处理之前进行调用,该方法的返回值布尔类型的,当它返回false时,表示请求结束,后续的interceptor和controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor的preHandle(),如果没有则调用controller中的方法
postHandle()该方法是在当前请求进行处理之后被调用,前提是preHandle()方法的返回值为true时才能被调用,且它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作
afterCompletion()该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,前提是preHandle()方法的返回值为true时才能被调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值