Spring 梳理 - filterinterceptoraop实现与区别 -第一篇

Posted 手握太阳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 梳理 - filterinterceptoraop实现与区别 -第一篇相关的知识,希望对你有一定的参考价值。

前言

项目中我们经常需要对RESTful api进行拦截,主流实现方法有filter、interceptor、aop,先说一下他们各自的实现。

Filter

AnimalFilter实现javax.servlet.Filter,项目启动时已初始化完成,可在控制台看到打印的初始化日志。

    @Component
    public class AnimalFilter implements Filter {
     
        private Logger logger = LoggerFactory.getLogger(getClass());
     
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            logger.info("animalFilter 初始化。。。");
        }
     
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            logger.info("animalFilter doFilter 。。。");
            chain.doFilter(request,response);//过滤器将请求往下传递
        }
     
        @Override
        public void destroy() {
            logger.info("animalFilter 销毁。。。");
        }
    }

如何调用不被component修饰的filter,将上文中的component注解去除,通过下文方式,让注解生效并设置注解生效的url请求地址信息。

    @Configuration
    public class AnimalWebConfig {
     
        @Bean
        public FilterRegistrationBean animalFilter(){
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            AnimalFilter animalFilter = new AnimalFilter();
            filterRegistrationBean.setFilter(animalFilter);
            List<String> urlPattern = new ArrayList<>();
            urlPattern.add("/animal/getAnimalById/*");
            filterRegistrationBean.setUrlPatterns(urlPattern);
            return filterRegistrationBean;
        }
     
    }

由于filter获取的参数为ServletRequest request, ServletResponse response, FilterChain chain,无法知道是哪个类的那个方法调用,更无法知道调用时的参数。

Interceptor

首先编写一个AnimalInterceptor实现HandlerInteceptor方法,实现相应的三个方法,preHandle执行方法前执行返回的结果决定是否往下执行,postHandle当方法返回值时执行,afterCompletion无论成功或失败都将执行,前提是preHandler要返回true。

    @Component
    public class AnimalInterceptor implements HandlerInterceptor {
     
        private Logger logger = LoggerFactory.getLogger(getClass());
     
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String methodName = handlerMethod.getMethod().getName();
            logger.info("AnimalInterceptor:preHandle:methodName:" + methodName);
            logger.info("AnimalInterceptor:preHandle");
            return true;
        }
     
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            logger.info("AnimalInterceptor:preHandle:methodName:" + handlerMethod.getMethod().getName());
            logger.info("AnimalInterceptor:postHandle");
        }
     
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            logger.info("AnimalInterceptor:afterCompletion");
        }
    }

将写好的AnimalInterceptor注入到spring的interceptor注册中心即可

    @Component
    public class InterceptorConfig extends WebMvcConfigurerAdapter{
     
        @Autowired
        AnimalInterceptor animalInterceptor;
     
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(animalInterceptor);
        }
    }

虽然interceptor可以知道调用的controller,调用的方法,但获取不到调用方法的参数。

AOP

编写AnimalAspect如下,可将传递的参数打印出来,aop拦截规则设置请查看,https://blog.csdn.net/FU250/article/details/80219415

    @Aspect
    @Component
    public class AnimalAspect {
        private Logger logger = LoggerFactory.getLogger(getClass());
     
        @Around("execution(* com.imooc.security.demo.web.controller..*.*(..))")
        public Object handleAnimalController(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            Arrays.stream(proceedingJoinPoint.getArgs()).forEach(arg -> {
                logger.info("arg:"+arg);
            });
            logger.info("AnimalAspect");
            return proceedingJoinPoint.proceed();
        }
    }

三个拦截器的比较如下,根据自己的业务功能需求选择最合适的拦截器。



   

以上是关于Spring 梳理 - filterinterceptoraop实现与区别 -第一篇的主要内容,如果未能解决你的问题,请参考以下文章

Spring核心组件知识梳理

Spring知识梳理

Spring源码解析一(框架梳理)

Spring源码解析一(框架梳理)

Spring知识梳理

Spring事务源码梳理