Fork me on GitHub

springboot 过滤器、拦截器、切片(aspect)

  本文的环境基础:springboot web模块,aop模块,rest风格

  本文的测试功能:对UserController进行拦截,输出每个方法执行的耗时

  • spring boot过滤器:过滤器只能取到request,response等信息,不能获取正在过滤的类的信息和方法的信息,不能获取请求参数

   过滤器的实现有两种方式:

    • 通过@Component注解,直接将filter交给spring管理,但是这种方式时过滤所有请求,我没有找到配置过滤路径的地方,欢迎朋友多多指教
 1 @Component
 2 public class TimeFilter implements Filter {
 3     @Override
 4     public void init(FilterConfig filterConfig) throws ServletException {
 5         System.out.println("TimeFilter : init");
 6     }
 7 
 8     @Override
 9     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
10         System.out.println("TimeFilter : doFilter start");
11 
12         Long startTime = System.currentTimeMillis();
13 
14         filterChain.doFilter(servletRequest, servletResponse);
15 
16         System.out.println("TimeFilter : 执行耗时 -> " + (System.currentTimeMillis() - startTime) + "ms");
17 
18         System.out.println("TimeFilter : doFilter finish");
19     }
20 
21     @Override
22     public void destroy() {
23         System.out.println("TimeFilter : destroy");
24     }
25 }

      这是过滤器的日志打印,controller千篇一律,这里就不在赘述。

    • 通过配置类的形式,这种方式可以配置路径

      这里对上边的TimeFilter稍作修改,去掉@Component,然后在spring boot的带有@SpringBootApplication注解的主类的目录下级编写自定义WebConfig

 1 @Configuration
 2 public class WebConfig {
 3 
 4     @Bean
 5     public FilterRegistrationBean timeFilter() {
 6         FilterRegistrationBean bean = new FilterRegistrationBean();
 7 
 8         bean.setFilter(new TimeFilter());
 9 
10         List<String> urls = new ArrayList<>();
11         urls.add("/user/*");
12         bean.setUrlPatterns(urls);
13 
14         return bean;
15     }
16 
17 }

           启动测试,效果类同,只不过多了一个URL的判断

  • spring boot拦截器:拦截器可以在过滤器的基础上,可以获取类的信息和方法的信息,但是不能获得请求参数
    • 定义拦截器,注意:需要@Component,交给Spring管理
       1 @Component
       2 public class TimeInterceptor implements HandlerInterceptor {
       3     @Override
       4     public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
       5         System.out.println("TimeInterceptor : preHandle");
       6 
       7         httpServletRequest.setAttribute("startTime", System.currentTimeMillis());
       8 
       9         return true;
      10     }
      11 
      12     @Override
      13     public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object obj, ModelAndView modelAndView) throws Exception {
      14         System.out.println("TimeInterceptor : postHandle start");
      15 
      16         Long startTime = (Long) httpServletRequest.getAttribute("startTime");
      17         System.out.println("TimeInterceptor : 执行耗时 -> " + (System.currentTimeMillis() - startTime) + "ms");
      18 
      19         System.out.println("TimeInterceptor : 拦截类名 -> " + ((HandlerMethod) obj).getBean().getClass().getName());
      20         System.out.println("TimeInterceptor : 拦截方法名 -> " + ((HandlerMethod) obj).getMethod().getName());
      21 
      22         System.out.println("TimeInterceptor : postHandle finish");
      23     }
      24 
      25     @Override
      26     public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
      27         System.out.println("TimeInterceptor : afterCompletion");
      28         Long startTime = (Long) httpServletRequest.getAttribute("startTime");
      29         System.out.println("TimeInterceptor : 执行耗时 -> " + (System.currentTimeMillis() - startTime) + "ms");
      30         System.out.println("TimeInterceptor : exception -> " + e);31     }
      32 }

       

    • 配置类修改,这是在过滤器的基础上修改的
       1 @Configuration
       2 public class WebConfig extends WebMvcConfigurerAdapter {
       3 
       4     @Autowired
       5     private TimeInterceptor timeInterceptor;
       6 
       7     @Override
       8     public void addInterceptors(InterceptorRegistry registry) {
       9         registry.addInterceptor(timeInterceptor);
      10     }
      11 
      12     @Bean
      13     public FilterRegistrationBean timeFilter() {
      14         FilterRegistrationBean bean = new FilterRegistrationBean();
      15 
      16         bean.setFilter(new TimeFilter());
      17 
      18         List<String> urls = new ArrayList<>();
      19         urls.add("/user/*");
      20         bean.setUrlPatterns(urls);
      21 
      22         return bean;
      23     }
      24 
      25 }
    • 测试结果,结论:首先进入filter --> 之后进入interceptor的preHandler --> 之后进入controller执行 --> interceptor postHandle --> interceptor afterCompletion --> filter,执行完毕

       当无异常抛出时,postHandle 和afterCompletion都会执行,当有异常抛出时,postHandle 不会执行,但是afterCompletion仍会执行,我们可以在这里对异常进行处理

    

  • spring boot aspect:切点在过滤器和拦截器的基础上,还可以获取请求参数
    • 定义切点,关于切点的定义,可以参考  https://docs.spring.io/spring/docs/4.3.14.RELEASE/spring-framework-reference/htmlsingle/#aop-pointcuts
       1 @Component
       2 @Aspect
       3 public class TimeAspect {
       4 
       5     @Around("execution(* com.mright.platform.controller.UserController.*(..))")
       6     public Object handleControllerMethod(ProceedingJoinPoint point) throws Throwable {
       7         System.out.println("TimeAspect : start");
       8         Long startTime = System.currentTimeMillis();
       9 
      10         Object[] args = point.getArgs();
      11         Arrays.stream(args).forEach(arg -> {
      12             System.out.println("TimeAspect : 参数 -> " + arg);
      13         });
      14 
      15         Object object = point.proceed();
      16 
      17         System.out.println("TimeAspect : finish");
      18 
      19         System.out.println("TimeAspect : 执行耗时 -> " + (System.currentTimeMillis() - startTime) + "ms");
      20         return object;
      21     }
      22 
      23 }

       

    • 运行结果如下,执行顺序显而易见,filter --> interceptor --> aspect

    

  

posted @ 2018-03-25 16:51  jfBoyFriend  阅读(375)  评论(0)    收藏  举报