背景
在工作中看到了不少项目用到了拦截器,这里去总结一下spring-boot使用拦截器。拦截器是Spring提供的HandlerInterceptor(拦截器),其功能和过滤器类似,但是提供更精细的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request的内容,但可以通过抛出异常(或者返回false)来暂停request的执行。
使用步骤
配置拦截器也很简单,spring给我们提供了WebMvcConfigurerAdapter,我们在addInterceptors方法中添加注册拦截器即可。总结起来就是三步:
1.创建我们自己的拦截器类并实现HandlerInterceptor接口。
2.创建一个Java类继承WebMvcConfigurerAdapter,并重写addInterceptors方法。
3.实例化我们自定义的拦截器,然后将对象手动添加到拦截器链中。
代码示例
自定义Session信息写入ThreadLocal
@Slf4j
@Component
public class SessionInterceptor implements HandlerInterceptor {
@Resource
private RequestHelper requestHelper;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
log.info("SessionInterceptor preHandle方法,在请求方法之前调用,Controller方法调用之前");
// MOCK一个SessionUser对象,放入ThreadLocal中
SessionUser sessionUser = new SessionUser();
sessionUser.setId(2L).setName("夸克");
requestHelper.setSessionUser(sessionUser);
// 只有这个方法返回true 请求才能继续下去
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)
throws Exception {
log.info("SessionInterceptor postHandle方法,请求处理之后调用,但是在视图被渲染之前(Controller方法调用之后)");
// 这里可以去做sessionUser的清除 防止内存泄漏
requestHelper.clearSession();
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
log.info("SessionInterceptor afterCompletion方法,在整个请求结束之后调用,也就是在Dispatcher渲染了整个视图之后进行(主要进行资源清理工作)");
if (Objects.nonNull(requestHelper.getSessionUser())) {
requestHelper.clearSession();
}
}
}
可以看到实现了HandlerInterceptor接口之后,要实现其中的三个方法。
preHandle方法:在请求controller方法之前调用,这里就可以做一些session对象的校验及写入ThreadLocal方便方法调用等。只有这个方法返回true,请求才能继续下去。
postHandle方法:这个方法是在请求了controller方法之后但在视图渲染之前调用的。这里可以去做ThreadLocal中资源的清除。
afterCompletion方法:这个方法是在整个请求结束之后调用的,也就是在Dispatcher渲染整个视图之后进行的,主要进行资源清理工作。(这里也是去补偿了ThreadLocal中资源的清除)。
注册拦截器
在WebMvcConfigurerAdapter的子类中注册这个拦截器。WebMvcConfigurerAdapter看名字就提供了很多spring