引子
今天在项目中,用到了拦截器相关知识,因此写一篇博文,记录拦截器相关知识,为以后巩固知识所用。
拦截器的定义
Spring要求处理器的拦截器都要实现接口org.springframework.web.servlet.HandlerInterceptor。
HandlerInterceptor接口需要实现的三个方法:
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
- preHandle方法:在处理器之前执行的前置方法,这样Spring MVC可以在进入处理器前处理一些方法了。注意,它将返回一个boolean值,会影响到后面Spring MVC的流程。
- postHandler方法:在处理器之后执行的后置方法,处理器的逻辑完成后运行它。
- afterCompletion方法:无论是否产生异常都会在渲染视图后执行的方法。
有了拦截器的定义,我们并不能马上开发拦截器,还要知道拦截器的执行流程:
在进入处理器之前或者之后处理一些逻辑,或者在渲染视图之后处理一些逻辑,都是允许的。有时候要自己实现一些拦截器,以加强请求的功能。注意,当前置方法返回false时,就不会在执行后面的逻辑了。在拦截器中可以完成前置方法、后置方法和完成方法的相关逻辑。
注册拦截器
我选择使用创建一个配置类,继承WebMvcConfigurerAdapter进行拦截器的注册。
@Component
public class WendaWebConfiguration extends WebMvcConfigurerAdapter {
@Autowired
PassportInterceptor passportInterceptor;
@Autowired
LoginRequiredInterceptor loginRequiredInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(passportInterceptor);
registry.addInterceptor(loginRequiredInterceptor).addPathPatterns("/user/*");
super.addInterceptors(registry);
}
}
至此,拦截器配置、注册完成,可以投入使用了!
多个拦截器执行顺序
多个拦截器会以一个怎么样的顺序执行呢?
假如配置了三个拦截器,正常情况下,会打印如下测试日志:
......
preHandler1
preHandler2
preHandler3
...控制器逻辑日志
postHnadler3
postHnadler2
postHnadler1
...完成方法
afterCompletion3
afterCompletion2
afterCompletion1
在正常情况下,Spring会先从第一个拦截器开始进入前置方法,这样前置方法是按配置顺序运行的,然后运行处理器的代码,最后运行处理器的代码,最后运行后置方法。注意,后置方法和完成方法则是按照配置逆序运行的,这和责任链模式的运行顺序是一致的。
如果有些时候前置方法可能返回false,那么返回false会怎么样呢?
当其中的一个preHandler方法返回为false后,按配置顺序,后面的preHandler方法都不会运行了,而控制器和所有的后置方法postHandler也不会再运行。执行过preHandler方法且该方法返回为true的拦截器的完成方法(afterCompletion)会按照配置的逆序运行。