一、应用场景
有时候在控制器处理请求前或处理后需要对请求进行一些操作,比如验证用户是否登录等需求。这时候可能就会需要使用到拦截器。
二、使用自定义拦截器
使用自定义拦截器大致可以分为两步:
- 实现
HandlerInterceptor
接口,自定义拦截器实体。 - 实现
WebMvcConfigurer
接口,配置自定义拦截器。
举个简单的例子
第一步,自定义拦截器实体。
public class MyInterceptor implements HandlerInterceptor {
@Override
// 第三个参数为被拦截请求的控制器 HandlerMethod
// 返回值:true表示继续流程(如调用下一个拦截器或处理器);
// false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 打印一下这个参数
if (handler instanceof HandlerMethod) {
System.out.println(((HandlerMethod) handler).getMethod().toString());
}
System.out.println("该方法将在请求处理之前进行调用,进入控制器前");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用");
}
}
第二步:配置自定义拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
// 添加拦截的路径,这里拦截所有路径
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
}
@Bean
// 注册自定义拦截器bean到容器
MyInterceptor myInterceptor() {
return new MyInterceptor();
}
}
第三步:测试一下
@RestController
@RequestMapping("/Hello")
public class HelloSpringBoot {
@GetMapping("/SpringBoot")
public R hello() {
return R.ok().put("hello", "Hello SpringBoot!");
}
}
控制台打印,发现hello
方法被拦截了
三、配合自定义注解食用
配合自定义注解,可以进一步筛选哪些控制器接受操作。举个简单的例子,某些控制器只接收已登录的用户请求,就可以这么操作。
首先自定义一个注解,自定义注解需要参考点这里
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Login {
}
接下来还是定义拦截器的流程
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Login annotation;
// 检验是不是控制器,如果不是放行
if (handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
} else {
return true;
}
// 检验是否添加了Login注解,如果没添加放行
if (annotation == null) {
return true;
}
// 下面假装做一下检验token是否为空的业务
String token = request.getHeader("token");
if (token == null) {
System.out.println("你不是自己人");
} else {
System.out.println("这是友军");
}
return true;
}
}
配置一下这个拦截器,把之前的那个先注上
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
// 添加拦截的路径,这里拦截所有路径
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
}
@Bean
// 注册自定义拦截器bean到容器
MyInterceptor myInterceptor() {
return new MyInterceptor();
}
@Bean
LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
}
控制器加上注解@Login
@RestController
@RequestMapping("/Hello")
public class HelloSpringBoot {
@Login
@GetMapping("/SpringBoot")
public R hello() {
return R.ok().put("hello", "Hello SpringBoot!");
}
}
然后用postman模拟给Header加上token和不加,分别请求测试一下,完全OK