Springboot中拦截器的使用与源码简易理解
第一篇博文想记录一下最近在基于springboot框架开发的系统中使用频率非常高的拦截器。废话不多说,开始吧!
一、初印象
相信学习过springmvc的小伙伴都拦截器一定不陌生,对于拦截器我们要知道的几个点在于:
- SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
- 过滤器与拦截器的区别:拦截器是AOP思想的具体应用( 注意是思想!!!面试的时候不要说是SpringAop动态代理实现的,具体的实现原理后边会再交代。)
2.1.过滤器:
a. servlet规范中的一部分,任何java web工程都可以使用。
b.在配置文件中的url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截。
2.2.拦截器:
a.拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
b.拦截器只会拦截访问的控制器方法,如果访问的jsp/html/css/image/js是不会进行拦截的
二、拦截器使用
ok,再三确定了我们有使用到SpringMVC框架(我用的Springboot,包含SpringMVC了哈),那么我们开始操作。
- 自定义拦截器类实现HandlerInterceptor接口,按需要重写此接口中定义好的方法。分别为:preHandler()、postHandle()、afterCompletion()。
1.1以preHandler()为例,写一个简单的登录拦截逻辑:我们检查session中有没有参数loginUserName(已登录用户),如果不为空,则通过;如果为空那么往request域中添加msg参数返回给前台表单,最后俺们请求转发,再给他拦截,完事儿。
1.2这段简单逻辑想要告诉大家的就是:HandlerInterceptor接口中的三个方法都为boolean类型,返回true时,请求通过,返回false,请求拦截。
1.3三个方法的执行顺序,其实我们通过命名就可知。至于何时执行,大家可以做个测试:在本类上添加日志注释@Slf4j,然后我们将三个方法一一重写,方法逻辑中我们log.info一下不同内容,拦截时看看他们的执行顺序即可。
//图一
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("preHandle拦截的请求路径是{}",requestURI);
//登录检查逻辑
HttpSession session = request.getSession();
if (session.getAttribute("loginUserName") != null) {
return true;
}
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
- 写一个配置类实现WebMvcConfigurer接口并重写addInterceptors方法。
2.1形参registry调用方法addInterceptor()。
2.2其中addPathPatterns是负责拦截。excludePathPatterns是负责放行。(我们在拦截请求的同时会把静态资源也拦截掉,那我们需要使用页面样式等静态资源的时候,就无法显示了,所以此处做放行)
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//"/**"是将所有请求拦截 包括静态资源
registry.addInterceptor(new LoginInterceptor()).
addPathPatterns("/**").//拦截
excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");//放行
}
}
- 看到这里,有没有回忆到一些以前学习的内容呢?
-----首先@Configuration注释说明这是个配置类,他把这个类就注入到了容器中。 那我们当初学些SpringMVC的时候用配置文件,拦截器又是怎么写的呢?
-----springmvc-servlet.xml中配置拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean id="loginInterceptor" class="com.atouyang.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
三、源码理解
源码部分就不展开说,但是理解拦截器一定要搞懂HandlerInterceptor接口中方法的执行顺序。我们就将源码以文字形式描述出来。首先,我们假设我们有好几个拦截器。
- 顺序执行所有拦截器的 preHandle方法。
1.1如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
1.2如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的 afterCompletion; - 当preHandler方法执行完后,倒序执行postHandler方法。同上,返回true,则执行下一个postHandler,一旦出异常,倒序执行所有已经执行了的拦截器的 afterCompletion。
- 同理,postHandler处理完后,倒序执行 afterCompletion。
注意点:前面的步骤有任何异常都会直接倒序触发 afterCompletion。页面成功渲染完成以后,也会倒序触发 afterCompletion。
流程看完是不是不太好理解呢。此处贴上一张尚硅谷雷神课堂笔记上的图,帮助大家理解。
最后,想要深入学习拦截器源码的同学,这里贴上一篇好文链接。
链接: SpringMVC拦截器源码解析.
写到这里啦!谢谢大家阅读!欢迎互相学习监督!!!