SpringBoot自定义拦截器interceptor使用详解

2022-06-28 08:58:33

上一篇文章我们介绍了过滤器Filter使用详解,Filter是依赖于Servlet,即Filter生命周期由Servlet容器管理,这篇文章我们介绍一个可以存在于Servlet以外的也具有过滤功能的组件——由Spring提供的Interceptor拦截器;拦截器主要应用在日志记录,权限校验等安全管理方面比较多

Spring Boot拦截器Intercepter详解

  1. 创建自定义拦截器实现HandlerInterceptor接口,并按照自定义要求重写指定方法
  2. 需要一个配置类实现WebMvcConfigurer 接口,并添加@Configuration注解
  3. 在配置类中重写addInterceptors方法,添加要拦截的url地址以及需要排除拦截的url地址

HandlerInterceptor接口源码:

publicinterfaceHandlerInterceptor{defaultbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{returntrue;}defaultvoidpostHandle(HttpServletRequest request,HttpServletResponse response,Object handler,@NullableModelAndView modelAndView)throwsException{}defaultvoidafterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,@NullableException ex)throwsException{}}

根据源码可看出HandlerInterceptor接口提供了三个default方法,这三个方法的各有各的作用,用户想要自定义一个指定拦截规则的拦截器,需要重写其中一个或多个方法,这三个方法作用如下:

  • preHandle: preHandle方法的作用是当请求在进入Controller之前拦截请求,对请求进行预处理,如登录验证或单点登录Cookie解析等都可以在此方法中执行,该方法由返回值,返回true表示放行进入到Controller层,false则请求结束返回错误相应信息
  • postHandle: postHandle方法是在请求被Controller处理完但是还并未传递到网页模板进行渲染拦截,即Controller处理完,还返回ModelAndView之前执行该方法,可以操控ModelAndView的值;所以该方法多了一个参数ModelAndView对象,这个参数包含了Controller处理完后需要传递的Model参数,因此,我们可以在该方法通过ModelAndView对象对返回给前端的视图作一定的修改
  • afterCompletion: afterCompletion方法作用就是做一些收尾工作,在ModelAndView返回给前端进行渲染后执行,比如有时候我们需要把每个线程的局部变量(如User信息)放入到ThreadLocal中,为了防止内存泄漏在最后需要清除ThreadLocal的内容,此操作就可以放在该方法中执行

再来看看WebMvcConfigurer源码:

publicinterfaceWebMvcConfigurer{defaultvoidconfigurePathMatch(PathMatchConfigurer configurer){}defaultvoidconfigureContentNegotiation(ContentNegotiationConfigurer configurer){}defaultvoidconfigureAsyncSupport(AsyncSupportConfigurer configurer){}defaultvoidconfigureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){}defaultvoidaddFormatters(FormatterRegistry registry){}defaultvoidaddInterceptors(InterceptorRegistry registry){}defaultvoidaddResourceHandlers(ResourceHandlerRegistry registry){}defaultvoidaddCorsMappings(CorsRegistry registry){}defaultvoidaddViewControllers(ViewControllerRegistry registry){}defaultvoidconfigureViewResolvers(ViewResolverRegistry registry){}defaultvoidaddArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers){}defaultvoidaddReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers){}defaultvoidconfigureMessageConverters(List<HttpMessageConverter<?>> converters){}defaultvoidextendMessageConverters(List<HttpMessageConverter<?>> converters){}defaultvoidconfigureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers){}defaultvoidextendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers){}@NullabledefaultValidatorgetValidator(){returnnull;}@NullabledefaultMessageCodesResolvergetMessageCodesResolver(){returnnull;}}

根据源码可看出WebMvcConfigurer提供了多个方法,并且也都是default方法,也是根据我们自定义配置重写其中一个或多个方法,这里就介绍以下两个比较常用的方法:

  • addInterceptors: 从该方法名就可以了解到该方法是添加拦截器,即将拦截器交给IOC去执行,拦截器的需要拦截的路径以及需要排除拦截的路径在该方法中配置
  • addResourceHandlers: 该方法的作用是配置静态资源路径,即某些请求需要读取某个路径下的静态资源内容,需要配置该静态资源的路径,通过该方法可以统一给这些请求配置指定静态资源路径

Intercepter应用实例

我们自定义一个获取并返回某个静态资源的内容以及整个请求所花费的时间拦截器

自定义的MyInterceptor:

importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;publicclassMyInterceptorimplementsHandlerInterceptor{privatestaticfinalLogger LOGGER=LoggerFactory.getLogger(MyInterceptor.class);privatestaticfinalThreadLocal<Long> START_THREAD_LOCAL=newThreadLocal<>();@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{String uri= request.getRequestURI();
        LOGGER.info(uri+" preHandle");Long startTime=System.currentTimeMillis();//获取开始时间
        START_THREAD_LOCAL.set(startTime);//线程绑定变量(该数据只有当前请求的线程可见)returntrue;}@OverridepublicvoidpostHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{String uri= request.getRequestURI();
        LOGGER.info(uri+" postHandle");Long startTime= START_THREAD_LOCAL.get();//得到线程绑定的局部变量(开始时间)Long endTime=System.currentTimeMillis();//2、结束时间Long time= endTime- startTime;
        LOGGER.info("http request all time: "+ time+"ms");}@OverridepublicvoidafterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throwsException{String uri= request.getRequestURI();
        LOGGER.info(uri+" afterCompletion");if(START_THREAD_LOCAL!=null){
            START_THREAD_LOCAL.remove();// 移除ThreadLocal中的局部变量}}}

interceptor配置类:

importcom.eureka.intercrpotor.MyInterceptor;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;@ConfigurationpublicclassInterceptorConfigimplementsWebMvcConfigurer{@BeanpublicMyInterceptormyInterceptor(){returnnewMyInterceptor();}@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(myInterceptor())// 添加拦截器.addPathPatterns("/**")// 配置拦截请求url( ** 表示拦截所有请求url).excludePathPatterns("/hello");// 排除某些不需要拦截的请求url(即带有/hello请求不会被拦截)}@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/**")// 配置需要添加静态资源的请求url.addResourceLocations("classpath:/mydata/");//配置静态资源路径}}

测试:
Controller类:

importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassTestController{@GetMapping("/test/interceptor")publicResponseEntity<String>testInterceptor(){returnResponseEntity.ok("successful");}}

静态资源:在这里插入图片描述


启动项目后访问 localhost:60011/test/interceptor:
在这里插入图片描述


控制台打印的日志:
在这里插入图片描述


我们再通过url访问静态资源请求 localhost:60011/test.jpg

  • 作者:Fly丶X
  • 原文链接:https://blog.csdn.net/weixin_44947701/article/details/122147104
    更新时间:2022-06-28 08:58:33