SpringMVC拦截器(Interceptor)是什么?
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现
拦截器和过滤器区别
补充
过滤器:在所有资源之前执行
拦截器:在前端控制器之前执行
图示:
拦截器执行顺序:
-
拦截器的preHandle() 执行顺序由拦截器在springMVC的配置顺序决定
-
每个拦截器的afterCompletion()方法是否执行,由自己拦截器的preHandle()的返回值决定
返回true: 执行, 返回false: 不执行
-
拦截器的postHandle() ,处理器是否执行: 由所有的拦截器链的preHandle()决定
都返回true,才执行, 只要有一个返回false, 不执行
-
postHandle(), afterCompletion() 执行顺序与拦截器在springMVC的配置顺序相反
图示:
实现拦截器的步骤
5. 编写一个类实现拦截器接口HandlerInterceptor
/**
* 拦截器
*/
@Slf4j
public class AInterceptor implements HandlerInterceptor {
/**
* 在处理器之前执行, 决定处理器是否执行
* 是否放行,由该方法的返回值决定: true: 放行 false: 不放行
* 使用场景: 权限控制, 访问控制
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("AInterceptor的preHandle()...");
return true;
}
/**
* 处理器执行代码,但是在未返回视图之前执行
* 场景: 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("AInterceptor的postHandle()...");
}
/**
* 在处理器完成之后, 执行
* 使用场景: 释放资源, 日志记录
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("AInterceptor的afterCompletion()...");
}
}
- 编写逻辑代码
@RestController
@Slf4j
@RequestMapping("hello")
public class HelloController {
@GetMapping("sayHello")
public String sayHello(){
log.info("HelloController的sayHello...");
return "hello";
}
}
- 在springmvc配置文件中进行配置
<mvc:interceptor>
<!--配置拦截的路径:
/** : 拦截当前路径以及后台所有
-->
<mvc:mapping path="/**"/>
<!--配置拦截器-->
<bean class="com.fs.interceptors.AInterceptor"></bean>
</mvc:interceptor>
打印结果:
上面说了,拦截器是一条链状,可以配置多个拦截器。
现在测试一下多个拦截器之间,方法的执行顺序
配置多个拦截器:
<!--拦截器的配置-->
<mvc:interceptors>
<!--单个拦截器配置-->
<mvc:interceptor>
<!--配置拦截的路径:
/** : 拦截当前路径以及后台所有
-->
<mvc:mapping path="/**"/>
<!--配置拦截器-->
<bean class="com.fs.interceptors.AInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!--配置拦截的路径:
/** : 拦截当前路径以及后台所有
-->
<mvc:mapping path="/**"/>
<!--配置拦截器-->
<bean class="com.fs.interceptors.BInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
打印结果:
总结:
1.preHandle按拦截器定义顺序调用
2.postHandler按拦截器定义逆序调用
3.afterCompletion按拦截器定义逆序调用
4.postHandler在拦截器链内所有拦截器返成功调用
5.afterCompletion只有preHandle返回true才调用