SpringBoot中使用拦截器的配置详解
作者:Mu_Mu是一只小白
1. 应用场景
拦截器是 AOP 的一种实现,专门拦截对动态资源的后台请求,即拦截对控制层的请 求。使用场景比较多的是判断用户是否有权限请求后台,更拔高一层的使用场景也有,比如拦截器可以 结合 websocket 一起使用,用来拦截 websocket 请求,然后做相应的处理等等。拦截器不会拦截静态 资源,Spring Boot 的默认静态目录为 resources/static,该目录下的静态页面、js、css、图片等等, 不会被拦截.
2. 定义拦截器
定义拦截器,只需要实现 HandlerInterceptor 接口, 该接口中有三个方法:
preHandle(……) 、 postHandle(……) 和 afterCompletion(……) 。
- preHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某个方法,且在这个方法执行之前。所以 preHandle(……) 方法可以决定是否将请求放行,这是通过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。
- postHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。所以在这个方法中有个ModelAndView 参数,可以在此做一些修改动作。
- afterCompletion(……) 方法:顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执行,这时做一些资源的清理工作,这个方法只有在 preHandle(……) 被成功执行后并且返回 true才会被执行。
2.1 自定义拦截类实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(MyInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); String methodName = method.getName(); logger.info("方法{}被拦截", methodName); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { logger.info("方法被执行,但是视图还未渲染"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { logger.info("方法执行完毕,进行资源清理"); } }
2.2 实现WebMvcConfigurer接口进行拦截配置
实现WebMvcConfigurer的这种配置会自动过滤静态资源;
@Configuration public class MyInterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } }
省略controller类
测试结果
10:52:16.316 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法test被拦截
10:52:16.344 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法被执行,但是视图还未渲染
10:52:16.344 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法执行完毕,进行资源清理
定义哪些不用拦截
取消拦截操作
如果我要拦截所有 /admin 开头的 url 请求的话,需要在拦截器配置中添加这个前缀,但是 在实际项目中,可能会有这种场景出现:某个请求也是 /admin 开头的,但是不能拦截,比如 /admin/login 等等
解决方案:
1.使用excludePathPatterns("/adminUser/login")
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/adminUser/login"); }
2.可以定义一个注解
该注解专门用来取消拦截操作,如果某个 Controller 中的方法我们 不需要拦截掉,即可在该方法上加上我们自定义的注解即可,下面先定义一个注解:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UnInterception { }
测试
controller类
@RestController @RequestMapping("/intercept") public class IntercepController { @UnInterception @RequestMapping("/hello") public String test() { return "success"; }
interceptor拦截类
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); String methodName = method.getName(); if (method.getAnnotation(UnInterception.class)!=null) { logger.info("方法{}不被拦截", methodName); return true; } logger.info("方法{}被拦截", methodName); return false; }
访问 localhost:8080/intercept/hello
结果
11:34:24.648 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法test不被拦截
11:34:24.676 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法被执行,但是视图还未渲染
11:34:24.679 [http-nio-8080-exec-1] INFO c.e.h.interceptors.MyInterceptor - 方法执行完毕,进行资源清理
到此这篇关于SpringBoot中使用拦截器的配置详解的文章就介绍到这了,更多相关SpringBoot拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!