SpringBoot中的MVC拦截器
在SpringBoot中所有的拦截器都需要实现HandIerInterceptor接口,HandIerInterceptor接口中有三个方法需要我们进行重写,这三个方法的执行顺序如下:
- 执行preHandle方法,该方法会返回一个布尔值。如果为false,则结束所有流程:如果为true,则执行下一步。
- 执行处理器逻辑,它包含控制器的功能。
- 执行postHandle方法。
- 执行视图解析和视图渲染。
- 执行afterCompletion方法。
在SpringBoot中自定义多个拦截器
自定义拦截器1
public class MulitiInterceptor1 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器之前执行");
// 返回true不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器方法完成之后,进入视图解析器处理之前执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在视图解析器处理完成,渲染数据到视图完成之后执行");
}
}
自定义拦截器2
public class MulitiInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器之前执行");
// 返回true不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器方法完成之后,进入视图解析器处理之前执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在视图解析器处理完成,渲染数据到视图完成之后执行");
}
}
自定义拦截器3
public class MulitiInterceptor3 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器之前执行");
// 返回true不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在controller处理器方法完成之后,进入视图解析器处理之前执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("【"+this.getClass().getSimpleName()+"】在视图解析器处理完成,渲染数据到视图完成之后执行");
}
}
自定义拦截器需要注册到SpringMVC中,所以这里自定义一个SpringMVC的配置类实现WebMvcConfigurer接口,将自定义的拦截器注册到SpringMVC中。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截所有的请求
// registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
// 注册拦截器到SpringMVC中拦截所有请求
registry.addInterceptor(new MulitiInterceptor1()).addPathPatterns("/**");
registry.addInterceptor(new MulitiInterceptor2()).addPathPatterns("/**");
registry.addInterceptor(new MulitiInterceptor3()).addPathPatterns("/**");
}
// @Override
// public void configureViewResolvers(ViewResolverRegistry registry) {
// registry.jsp("/jsp/",".jsp");
// }
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
}
至此拦截器已经注册完成,这里需要整合jsp视图来验证拦截器中的三个方法的执行顺序
SpringBoot整合jsp
1、添加maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--注意:spring boot对jsp的支持不是很好,在使用spring boot自带tomcat的同时,还需要引入另外的一个tomcat,以来如下所示,且scope属性需要被注释掉 -->
<!--注掉的原因是:maven默认scope是compile,表示打包时会把此包打入jar包中,而provided表示打包时不会打如jar包中,因为它默认是jar包中会提供,说白了就是你标注了provided就不会被打入jar包中,项目跑起来就肯定会有问题了 2019/12/4 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<!--<scope>provided</scope> 注意,这个scope需要被注释掉-->
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
第二步创建视图资源的目录
第三步在项目设置里面将新建的webapp目录设置成资源目录
第四步配置逻辑视图的前后缀信息,可以在application.properties文件中配置也可以在实现WebMvcConfigurer接口的配置类中进行配置,如果同时配置,则代码中的配置会覆盖配置文件中的内容。
spring.mvc.view.prefix=/jsp/
spring.mvc.view.suffix=.jsp
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/jsp/",".jsp");
}
}
第五步在idea启动的配置中配置项目启动的工作目录
编写jsp
<%@ page import="java.util.*" isELIgnored="false" %>
<%--设定页面传递参数的编码格式,所有页面的编码格式要统一--%>
<%request.setCharacterEncoding("utf-8");%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>jsp</title>
</head>
<body>
<%
System.out.println("渲染视图");
out.println("11111");
%>
</body>
</html>
写controller进行测试
@Controller
public class HelloController {
@GetMapping("/test")
public String hello(){
System.out.println("handle接受test请求,处理Controller中的hello方法执行了");
return "hello";
}
}
测试结果为:
从结果可以看出这个是责任链模式的规则,对于处理器前方法采用先注册先执行,而处理器后方法和完成方法则是先注册后执行的规则。