拦截器是 SpringMVC 中一个强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作。我们可以自己定义一个拦截器,Spring 要求处理器的拦截器都需要实现 org.springframework.web.servlet.HandlerInterceptor 接口,我们来看看该接口的源码:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
HandlerInterceptor 接口中定义了三个方法:
- preHandle 方法:在处理器之前执行的前置方法,SpringMVC 可以在进入处理器之前处理一些方法,方法默认返回一个 Boolean 值,true 代表放行,false 代表拦截
- postHandle 方法:在处理器之后执行的后置方法,处理器的逻辑完成后运行它
- afterCompletion 方法:无论是否产生异常都会在渲染视图后执行的方法
拦截器的定义
SpringMVC 配置拦截器有两种方式,一种是xml配置,一种是java配置,Spring4之后推荐使用java配置
<?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-4.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.5.xsd ">
<!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- /**的意思是所有文件夹及里面的子文件夹 /*是所有文件夹,不含子文件夹 /是web项目的根目录 -->
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址 -->
<!-- <mvc:exclude-mapping path="/userController/login"/> -->
<bean id="ManagerInterceptor" class="com.mall.Interceptor.ManagerInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/admin/details"/>
<bean id="OrderInterceptor" class="com.mall.Interceptor.OrderInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/shop/personal"/>
<bean id="UserInterceptor" class="com.mall.Interceptor.UserInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
这里的 xml 配置中是配置了三个拦截器,bean 节点中的 class 属性值为对应的拦截器全类包路径
定义一个拦截器实现 HandleInterceptor 接口
/**
* @Author: 98
* @Date: 2019-8-1 16:41
*/
public class WebAdminInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
创建一个java类,类上使用 @Configuration 表明这是个配置类
/**
1. @Author: 98
2. @Date: 2019-8-1 16:52
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
WebAdminInterceptor webAdminInterceptor(){
return new WebAdminInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(webAdminInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static");
}
}
拦截器的执行顺序
拦截器的执行顺序可以分成多种情况:
-
单个拦截器
执行的顺序为:
preHandle => postHandle => afterCompletion (前提 preHandle 方法返回true) -
多个拦截器,preHandle 方法均返回 true
执行的顺序为:
preHandle1
preHandle2
preHandle3
postHandle3
postHandle2
postHandle1
afterCompletion3
afterCompletion2
afterCompletion1 -
多个拦截器,其中一个或多个拦截器 preHandle 方法返回false,这里我们设置三个拦截器,将第二个拦截器的前置方法返回false
preHandle1
preHandle2
afterCompletion1
当其中的一个 preHandle 方法返回为false后,按照配置的顺序,后面的 preHandle 方法都不会运行,而控制器和所有的后置方法 postHandle 也不会再运行。