zoukankan      html  css  js  c++  java
  • Springboot 三种拦截Rest API的方法-过滤器、拦截器、切片

    过滤器方式实现拦截(Filter)

    通过继承Servlet的Filter类来实现拦截:

    @Component
    public class TimeFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("time filter init");
        }
        /**
         * 处理服务的请求时间
         * @param request
         * @param response
         * @param chain
         * @throws IOException
         * @throws ServletException
         */
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //System.out.println("time filter start");
            long start = System.currentTimeMillis();
            chain.doFilter(request,response);
            //System.out.println("time filter 耗时:" + (System.currentTimeMillis() - start));
            //System.out.println("time filter finish");
    
        }
        @Override
        public void destroy() {
            //System.out.println("time filter destroy");
        }
    }

    假如这个Filter是第三方jar提供的,怎么加入我们自己的工程呢?通过org.springframework.boot.web.servlet.FilterRegistrationBean来加入

    @Configuration
    public class WebConfig {
        
        @Bean
        public FilterRegistrationBean timeFilter() {
            
            FilterRegistrationBean registrationBean = new FilterRegistrationBean();
            
            TimeFilter timeFilter = new TimeFilter();
            registrationBean.setFilter(timeFilter);
            
            List<String> urls = new ArrayList<>();
            urls.add("/*");
            registrationBean.setUrlPatterns(urls);
            
            return registrationBean;
            
        }
    
    }

    拦截器方式实现拦截(Interceptor)

    此种方式可以获取到拦截的类名称、方法名称,不能获取到方法参数,原因是在dispatcherservlet源码中,经过preHandle才对方法参数通过request里面开始处理拼接)

    1.继承HandlerInterceptor,preHandle在控制器方法调用之前执行,postHandle在控制器方法正常执行后执行,afterCompletion不管控制器方法执行成功与否,都会执行;拦截器优于过滤器的地方就是拦截器有handler这个参数可以了解到针对哪个具体的方法进行了拦截。

    @Component
    public class TimeInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            //打印类名
            System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
            //打印方法名
            System.out.println(((HandlerMethod)handler).getMethod().getName());
            request.setAttribute("startTime",System.currentTimeMillis());
            return true;
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
            Long start = (Long)request.getAttribute("startTime");
            System.out.println("time intercept 耗时:" + (System.currentTimeMillis() - start));
        }
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception ex) throws Exception {
            System.out.println("afterCompletion");
            Long start = (Long)request.getAttribute("startTime");
            System.out.println("time intercept 耗时:" + (System.currentTimeMillis() - start));
            System.out.println("ex is" + ex);
        }
    }

    2. 配置拦截器注入到spring容器(配置类需要继承WebMvcConfigurerAdapter,重写addInterceptors,手动添加自定义拦截器来到达注入的目的),也可为异步请求加入拦截器

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Autowired
        private TimeInterceptor timeInterceptor;
    
        /**
         * 针对异步的拦截器配置,拦截异步请求
         * @param configurer
         */
        @Override
        public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
            super.configureAsyncSupport(configurer);
            //比如如下给异步服务请求添加拦截器
            //configurer.registerCallableInterceptors((CallableProcessingInterceptor) timeInterceptor);
        }
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(timeInterceptor);
        }
    }

    切片方式实现拦截(Aspect)

    可以拦截到类名、方法名,方法参数名

    @Aspect
    @Component
    public class TimeAspect {
        //切入点
        @Around("execution(* com.zlt.web.controller.UserController.*(..))")
        //增强
        public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
    
                System.out.print("time aspect start");
                Object[] args = pjp.getArgs();
                for (Object arg :args){
                System.out.println("arg is" + arg);
                }
                long start = System.currentTimeMillis();
                //调用被拦截的方法
                Object object = pjp.proceed();
                System.out.println("time filter 耗时:" + (System.currentTimeMillis() - start));
                System.out.println("time aspect end");
                return object; 
        }
    }

    小结

    区别:

    过滤器:可以拿到原始的HTTP请求和响应信息,拿不到处理请求的方法值信息 
    拦截器:既可以拿到HTTP请求和响应信息,也可以拿到请求的方法信息,拿不到方法调用的参数值信息 
    切片:可以拿到请求方法的传入参数值,拿不到原始的HTTP请求和响应的对象

    发起一个请求,若三者共存的情况下:

    正常运行顺序为:filter-interceptor-controllerAdvice-aspect-controller
    异常情况下:controller-aspect-controllerAdvice-interceptor-filter

  • 相关阅读:
    用户管理 之 Linux 系统中的超级权限的控制
    硬件管理 之 存储设备分区操作及文件系统管理概述
    用户管理 之 Linux 用户(User)查询篇
    软件工程——需求工程
    自动装载模块
    管理内核模块
    模块功能的注册和取消
    编程实现将任意的十进制整数转换成R进制数
    数据流图分析与设计
    软件工程——系统工程
  • 原文地址:https://www.cnblogs.com/lostyears/p/10706774.html
Copyright © 2011-2022 走看看