spring系列

基于Spring boot的拦截(Filter,Intercep

2019-07-08  本文已影响0人  Candy_糖果

问题

  1. 当客户端请求服务器接口时,我需要验证一下用户的登陆权限。接口少的时候,我可以在每个接口里验证,但当接口成百上千时,这种重复的工作就会显得很冗余
  2. 同理当客户端请求服务器接口时,我想要计算每个接口运行时花费的时间,开始时可以在代码的开始和结束计算时间,最后在返回时打印时间出来。但当接口成百上千时,这种重复的工作就会显得很冗余

解决思路

针对这种重复性问题,可以抽象出一层代理来解决

  1. 可以写一个抽象的类实现登陆权限验证,后边每一个Controller都继承这个抽象接口
  2. 还有框架自带的拦截,是在controller被调用前和后做的一个拦截,原理都是抽象出一层来解决这个重复性的问题

拦截

下面我们看看 spring boot 是怎么抽象出这层拦截

一共有三种方式,分别是 Filter,Interceptor,AOP

它们拦截的顺序
Filter -> Interception -> AOP -> 具体执行的方法 -> AOP-> @ControllerAdvice 全局异常处理-> Interception-> Filter

image.png

它们的共同点都是拦截,下边谈谈它们的不同点和场景的使用范围

  1. Filter 不依赖于框架,依赖于Servlet容器。网上有人说不能在该类里使用bean,经过测试后,是可以的,再要在类上加 @Component就可以被spring框架扫描到。
  2. Interceptor 依赖spring框架,是 AOP 的一种实现,建议优先使用Interceptor,而不是Filter。毕竟框架封装的,接口功能会更丰富一些
  3. AOP 是spring的一大特性,它也可以起到拦截的作用,不过主要用于拦截接口,注解,可以获取接口的参数,Interceptor,Filter都不能。

总的来说,拦截接口时,使用AOP,拦截Controller时,使用Interceptor

代码实现

下边我们看看它们的具体实现,很简单,就不一一解释了

Filter 实现

/**
 * Created jixinshi on 2019-07-08.
 */
@Component
@Slf4j
public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("========= before doFilter ===========");
        chain.doFilter(request, response);
        log.info("========= after doFilter ===========");
    }

    @Override
    public void destroy() {
    }
}

Interceptor 实现

/**
 * Created jixinshi on 2019-07-08.
 * 拦截器,继承 HandlerInterceptorAdapter,可以根据需求实现接口
 */
@Component
@Slf4j
public class TestInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("========= preHandle ===========");
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("========= postHandle ===========");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}
/**
 * Created jixinshi on 2019-07-08.
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Resource
    private TestInterceptor testInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(testInterceptor)
                .addPathPatterns("/**");
    }
}

AOP 实现

/**
 * Created jixinshi on 2019-07-08.
 */
@Component
@Aspect
@Slf4j
public class TestAspect {

    @Pointcut("execution(public * com.example.demo.controller.*Controller.*(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object function(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("========= before aspect ===========");
        Object proceed = proceedingJoinPoint.proceed();
        log.info("========= after aspect ===========");
        return proceed;
    }

}

另外,之前写了一篇 Spring AOP 通过注解的方式 打印接口执行的时间
请点这里

调用接口 hello/test

执行效果图

image.png

衍生问题

拦截涉及到Spring MVC框架的前与后,既然来都来了,下篇文章就让我们思考下Controller在Spring MVC中的地位,并如何被抽象?

写完了
https://www.jianshu.com/p/058216e3b543

参考

  1. SpringBoot中的拦截机制
  2. Spring:过滤器filter、拦截器interceptor、和AOP的区别与联系
  3. Spring 梳理 - filter、interceptor、aop实现与区别 -第二篇
  4. Filter,Interceptor,AOP 区别与实例

本文是基于自己理解写的,如果有错欢迎留言讨论

上一篇下一篇

猜你喜欢

热点阅读