一、拦截器执行顺序
二、应用场景
1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
2、权限检查:如登录检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
3、性能监控:典型的是慢日志。
4、自定义注解:实现自定义注解的功能。
三、HandlerInterceptorAdapter与HandlerInterceptor
HandlerInterceptor是一个接口,需要实现
public interface HandlerInterceptor {
/**
* 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
HandlerInterceptorAdapter是抽象类没有抽象方法,按需引入覆写就行
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
/**This implementation always returns {@code true}.*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/** This implementation is empty.*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
/**This implementation is empty.*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
/**This implementation is empty.*/
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
}
}
四、自定义拦截器与WebMvcConfigurer
WebMvcConfigurer是一个接口,旧的版本是继承WebMvcConfigurerAdapter
常用方法
/** 拦截器配置 */
void addInterceptors(InterceptorRegistry var1);
/* 视图跳转控制器 */
void addViewControllers(ViewControllerRegistry registry);
/** 静态资源处理*/
void addResourceHandlers(ResourceHandlerRegistry registry);
/** 默认静态资源处理器 */
void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
/** 这里配置视图解析器*/
void configureViewResolvers(ViewResolverRegistry registry);
/** 配置内容裁决的一些选项*/
void configureContentNegotiation(ContentNegotiationConfigurer configurer);
/** 解决跨域问题 */
public void addCorsMappings(CorsRegistry registry) ;
这里重点讲下addInterceptors(InterceptorRegistry var1)方法:注册拦截器
1、addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
2、addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")
对所有请求都拦截
3、excludePathPatterns:用于设置不需要拦截的过滤规则
4、拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
// 注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
ArrayList<String> commonPathPatterns = getExcludeCommonPathPatterns();
registry.addInterceptor(getTestInterceptor1()).addPathPatterns("/**").excludePathPatterns(commonPathPatterns.toArray(new String[]{}));
registry.addInterceptor(getTestInterceptor2()).addPathPatterns("/**").excludePathPatterns(commonPathPatterns.toArray(new String[]{}));
}
@Bean
TestInterceptor1 getTestInterceptor1() {
return new TestInterceptor1();
}
@Bean
TestInterceptor2 getTestInterceptor2() {
return new TestInterceptor2();
}
}
五、那底层是什么呢
基于责任链模式与JDK动态代理。
六、总结
- 拦截器执行顺序是按照WebMvcConfigurer配置中定义的顺序而定的。
- 会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。
- 然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。
- 在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)