目录
什么是拦截器
拦截器的实现
拦截器的使用
拦截路径
拦截器的执行流程
什么是拦截器
拦截器(Interceptor)是Spring框架提供的核心功能之一,主要用于拦截用户请求,在指定方法前后,根据业务需求执行预先设定的代码
拦截器允许开发人员提前预定义一些逻辑,在用户的请求响应前后执行,也可以在用户请求前阻止其执行,在拦截器当中,开发人员可以在应用程序中做一些通用性的操作
例如,可以通过拦截器拦截前端发来的请求,判断Session中是否有登录用户的信息,若有,则放行;若没有,则进行拦截
在了解了什么是拦截器之后,我们来学习如何实现拦截器
拦截器的实现
拦截器的使用分为两步:
1. 定义拦截器
2. 注册配置拦截器
我们首先来实现自定义拦截器:
实现 HandlerInterceptor 接口,并重写其所有方法:
@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("Interceptor: 目标方法执行前...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("Interceptor: 目标方法执行后...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("Interceptor 视图渲染完毕后...");}
}
preHandle():目标方法执行前执行,若返回true,则继续执行后续操作;若返回false,则中断后续操作
postHandle():目标方法执行后执行
afterCompletion():视图渲染完毕后执行,最后执行
定义好拦截器后,我们来注册配置拦截器:
实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法
@Configuration
public class WebConfig implements WebMvcConfigurer {// 自定义拦截器对象@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册自定义拦截器对象registry.addInterceptor(myInterceptor).addPathPatterns("/**"); // 设置拦截器拦截路径}
}
接下来,我们进行测试:
@RestController
@Slf4j
@RequestMapping("/test")
public class TestController {@RequestMapping("/t1")public void t1() {log.info("test t1...");}
}
启动服务,访问127.0.0.1:8080/test/t1,观察后端日志:
由于preHandle() 方法的返回值为true,因此执行完后就放行了,此时开始执行目标方法,目标方法执行完后就执行 postHandle() 方法 和 afterCompletion() 方法
将拦截器中 preHandle() 方法的返回值改为 false,再次运行、访问并观察日志:
可以看到,拦截器拦截了请求,并未进行响应
在简单使用了拦截器后,我们来继续学习拦截器的使用细节
拦截器的使用
拦截路径
拦截路径是指我们定义的拦截器对哪些请求生效
我们在注册配置拦截器时,通过 addPathPatterns() 方法指定要拦截哪些请求,也可以通过 excludePathPatterns() 指定不拦截哪些请求
在之前,我们配置的是 /**,表示拦截所有的请求
在拦截器中,除了可以设置 /** 拦截所有资源外,还有一些常见的拦截路径设置:
拦截路径 | 含义 | 举例 |
---|---|---|
/* | 一级路径 | 能匹配/user、/test、/login,但不能匹配 /test/t1 |
/** | 任意级路径 | 能够匹配所有请求 |
/test/* | /test下的一级路径 | 能匹配/test/t1,但不能匹配/test/t1/t11,也不能匹配 /user、/user/t1 |
/test/** | /test下的任意级路径 | 能匹配/test下的所有请求,如 /test/t1、/test/t1/t11,不能匹配 /user、/user/login |
以上拦截规则可以拦截项目中使用的URL,包括静态文件(图片文件、JS、CSS等文件)
拦截器的执行流程
未使用拦截器时,调用顺序为:
当使用拦截器后,会在调用 Controller 之前进行相应的业务处理:
当添加拦截器后,执行 Controller 方法之前,请求会先被拦截器拦截住,执行 preHandle() 方法,该方法会返回一个布尔类型的值。若返回 true,则表示放行本次操作,继续访问 controller 中的方法;若返回 false,则不会放行, controller中的方法也就不会执行
controller中的方法执行完毕后,再执行 postHandle() 方法 和 afterCompletion() 方法,执行完毕后,再响应数据
拦截器可用于检查用户的身份验证信息,并根据权限决定是否允许访问特定的页面或资源
例如,我们在实现登录验证功能时,就可以使用拦截器来实现强制登录功能
自定义拦截器 LoginInterceptor 并重写 preHandle() 方法,判断用户是否登录,若登录,则返回true,放行,继续执行 controller中方法;若用户未登录,则返回false,进行拦截,并设置http状态码为 401