SpirngBoot中使用Interceptor拦截器
本篇文章可以带您快速复习拦截器的使用,食用本篇文章前您必须熟练掌握并拥有基于注解配置SpringMVC的能力!
1.快速回顾拦截器
首先我们需要通过以下图片回顾一下SpringMVC中拦截器的执行位置。

拦截器(
Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
- 总结:拦截器就是用来做增强
拦截器和过滤器之间的区别
- 归属不同:
Filter属于Servlet技术,Interceptor属于SpringMVC技术 - 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
- 归属不同:

2.SpringBoot中使用拦截器
创建一个
SpringBoot工程并勾选web开发的依赖
创建完毕后我们需要编写一个
UserController类进行测试@RestController @RequestMapping("/user") public class UserController { @GetMapping("/login") public String login(){ return "登陆成功!"; } @GetMapping("/register") public String register(HttpSession session){ //模拟用户注册,将用户信息存储session域中 session.setAttribute("user","user"); return "注册成功!"; } } java然后我们通过浏览器访问这两个路径
/login、/register通过访问可以发现两个接口均可正常访问,但这显然不是我们所期望的,我们期望的是用户在没有注册的情况下直接访问登录接口是失败的,因此我们需要通过添加一个拦截器的功能来实现。

新建一个拦截器
MyInterceptor并实现HandleInterceptor接口@Component //将这个类放进spring的容器中 public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); //从session域中获取user Object user = session.getAttribute("user"); if (user == null){ //如果user为null,说明用户没有注册,进行拦截 response.setStatus(401); return false; } return true; } } java新建一个
SpringMVC的配置类SringMvcConfig用来添加拦截器@Configuration public class SpringMvcConfig implements WebMvcConfigurer { @Resource private MyInterceptor myInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //添加我们的拦截器,使其生效,addPathPatterns()方法是执行拦截了拦截的路径,默认拦截全部路径 registry.addInterceptor(myInterceptor).addPathPatterns("/user/login"); } } java此时我们重启项目再次访问两个路径

3.拦截器的方法说明
我们自定义的拦截器在实现了
HandlerInterceptor接口后我们可以选择实现三个方法
3.1 前置处理方法
控制器方法执行之前执行
preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法。返回
false表示拦截,即不调用控制器方法。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle()方法被执行!");
return true;
}
javarequest:请求对象response:响应对象handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装
使用handler参数,可以获取方法的相关信息
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod hm = (HandlerMethod)handler;
String methodName = hm.getMethod().getName();//可以获取方法的名称
System.out.println("preHandle..."+methodName);
return true;
}
java3.2 后置处理方法
原始方法运行后运行,如果原始方法被拦截,则不执行
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object handler, ModelAndView mv) throws Exception {
System.out.println("postHandle()方法被执行!");
}
java前三个参数和上面的是一致的。
modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整因为咱们现在都是返回
json数据,所以该参数的使用率不高。
3.3 完成处理方法
拦截器最后执行的方法,无论原始方法是否执行
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion()方法被执行!");
}
java前三个参数与上面的是一致的。
ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理 ,因为我们现在已经有全局异常处理器类,所以该参数的使用率也不高。
这三个方法中,最常用的是preHandle(),在这个方法中可以通过返回值来决定是否要进行放行,我们可以把业务逻辑放在该方法中,如果满足业务则返回true放行,不满足则返回false拦截。
4.多个拦截器执行顺序
目前,我们在项目中只添加了一个拦截器,如果有多个,该如何配置?配置多个后,执行顺序是什么?
- 当配置多个拦截器时,形成拦截器链
- 拦截器链的运行顺序参照拦截器添加顺序为准
- 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作

preHandle:与配置顺序相同,必定运行
postHandle:与配置顺序相反,可能不运行
afterCompletion:与配置顺序相反,可能不运行。
这个顺序不太好记,最终只需要把握住一个原则即可:以最终的运行结果为准
