美文网首页
Springboot中的过滤器、拦截器、切片

Springboot中的过滤器、拦截器、切片

作者: _薯条 | 来源:发表于2019-03-03 23:39 被阅读0次

    自定义过滤器(filter)

    //@Component
    public class MyFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("my filter init");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("my filter start");
            long start = new Date().getTime();
            filterChain.doFilter(servletRequest, servletResponse);
            System.out.println("my filter 耗时:" + (new Date().getTime() - start));
            System.out.println("my filter finish");
        }
    
        @Override
        public void destroy() {
            System.out.println("my filter destroy");
        }
    }
    

    自定义的filter可以不加上@Componet注解,就比如我们开发中经常需要增加第三方的过滤器,但是引入的第三方包里的过滤器又不能修改源码,在以前ssm框架中开发时,可以将filter配置在web.xml文件中,而Springboot中并没有web.xml文件,所以需要单独写配置文件配置:

    @Configuration
    public class WebConfig {
    
        @Bean
        public FilterRegistrationBean timeFilter() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            MyFilter myFilter = new MyFilter();
            filterRegistrationBean.setFilter(myFilter);
            // 设置MyFile在指定url起作用
            List<String> urlList = new ArrayList<>();
            urlList.add("/*");
            filterRegistrationBean.setUrlPatterns(urlList);
            return filterRegistrationBean;
        }
    
    }
    

    使用配置文件配置我们自己写的filter时,可以配置filter在指定的url生效,如果直接使用@Compnent注解,则filter在所有的的url都生效。

    自定义拦截器(interceptor)

    @Component
    public class MyInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            request.setAttribute("startTime", new Date().getTime());
            System.out.println(((HandlerMethod) handler).getBean().getClass().getName());  // 获取处理请求的类名称
            System.out.println(((HandlerMethod) handler).getMethod().getName());  // 获取处理请求的方法名
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
            long startTime = (long) request.getAttribute("startTime");
            System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
            System.out.println("afterCompletion");
            long startTime = (long) request.getAttribute("startTime");
            System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
            System.out.println("ex is " + e);
        }
    
    }
    

    自定义拦截器后,还需要单独写配置文件进行配置:

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Autowired
        private MyInterceptor myInterceptor;
    
        // 重写WebMvcConfigurerAdapter类的addInterceptors方法,添加自己的拦截器
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(myInterceptor);
        }
    
    }
    

    切片(aspect)

    引入maven依赖:

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    
    @Aspect
    @Component
    public class MyAspect {
    
        @Around("execution(* com.sinosoft.controller.UserController.*(..))")
        public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("my aspect start");
            Object[] args = pjp.getArgs();  // 获取到方法参数的值
            for (Object arg : args) {
                System.out.println("arg is " + arg);
            }
            long startTime = new Date().getTime();
            Object object = pjp.proceed();
            System.out.println("my aspect 耗时:" + (new Date().getTime() - startTime));
            System.out.println("my aspect end");
            return object;
        }
    
    }
    

    定义过滤器、拦截器、切片后运行结果,测试其执行顺序:

    my filter start
    preHandle
    com.sinosoft.controller.UserController$$EnhancerBySpringCGLIB$$89062ea2
    getInfo
    my aspect start
    arg is “自己输入的参数”
    进入controller服务   // controller调用方法中打印
    my aspect 耗时:2
    my aspect end
    postHandle
    my interceptor 耗时:41
    afterCompletion
    my interceptor 耗时:41
    ex is null
    my filter 耗时:55
    my filter finish
    

    从执行结果可以看出,执行顺序如图:

    执行顺序图

    总结:

    1、过滤器能够拿到原始的http请求和响应的信息,但是拿不到真正处理请求的方法的信息;
    2、拦截器既能拿到原始的http请求和响应的信息,也能拿到真正处理请求的方法的信息,但是拿不到方法被调用的时候,那个被调用方法的参数的值;
    3、切片可以拿到方法被调用的时候,方法参数传进来的值,但是拿不到原始的http请求和响应的对象。

    相关文章

      网友评论

          本文标题:Springboot中的过滤器、拦截器、切片

          本文链接:https://www.haomeiwen.com/subject/aksvuqtx.html