Filter和Interceptor区别

今天在搬砖的时候写逻辑需要拦截方法做切面处理,脑瓜中浮现出了两个玩意,一个是Filter(过滤器),另一个是Interceptor(拦截器),一时竟然不知道用哪个了,关于他们的具体区别和使用场景,大脑有点略懵,然后学习了一波,特此在这进行一个记录,方便再懵的时候进行查阅。

Filter

1、相对于Interceptor特殊的一点是可以获取到方法的入参值。

2、可以拿到请求响应的内容。

3、拦截器依赖servlet容器。

使用场景

1、用于拦截并处理web请求,做一些拦截处理或者耗时统计处理。

2、对响应结果进行统一封装处理或者压缩处理等。

3、一些api网关中间件的实现都是基于过滤器实现的比如zuul等。

贴一波过滤器demo


@Slf4j
@WebFilter(urlPatterns = "/test/*", filterName = "myFilter")
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
      log.info(">>>>>>>>>>>>>>filter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestUri = request.getRequestURI();
        log.info("请求url: {}",requestUri);
        String method = request.getMethod();
        log.info("请求method: {}",method);
        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("请求parameter: {}",parameterMap);
        StopWatch sw = new StopWatch();
        sw.start("method:【"+method+"】 execute time");
        filterChain.doFilter(servletRequest,servletResponse);
        sw.stop();
        log.info(sw.prettyPrint());
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

Interceptor

1、基于java的反射机制实现的,不依赖servlet容器。

2、可以控制请求的控制器和方法,获取不到方法里面的参数(只能获取参数名称,拿不到值)。

3、一般用于服务拦截,而不是web请求拦截。

@Component
public class FirstHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object hanlder) {
         System.out.println("拦截器.preHandle 开始执行。。。");
         System.out.println(hanlder.getClass().getSimpleName());
         System.out.println(((HandlerMethod) hanlder).getBean().getClass().getName());
        httpServletRequest.setAttribute("start", currentTimeMillis());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object hanlder, ModelAndView modelAndView) {
         System.out.println("拦截器.postHandle 开始执行。。。");
        long start = (long) httpServletRequest.getAttribute("start");
         System.out.println("postHandle执行时间为:" + (currentTimeMillis() - start));

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object hanlder, Exception e) {
        //会打印两次 spring里面的basic error 也会被拦截
         System.out.println("拦截器.afterCompletion 开始执行。。。");
        long start = (long) httpServletRequest.getAttribute("start");
         System.out.println("afterCompletion执行时间为:" + (currentTimeMillis() - start));
        System.out.println("\n ex is :" + e+"\n");
    }
}

HandlerInterceptor三个方法:preHandle、postHandle和afterCompletion的执行时间点如下:

preHandle:在HandlerMapping确定使用哪个Handler处理请求之后,HandlerAdapter调用Handler之前,在该阶段HandlerInterceptor可以修改Request和Response。

postHandle:在HandlerAdapter调用Handler之后,DispatcherServlet渲染视图之前。实际上在调用postHandler之前HandlerAdapter已经完成Response写并提交,因此postHandler无法修改Response。如果有修改Response的场景,可以使用ResponseBodyAdvice接口。

afterCompletion:请求处理完成之后调用,适合做一些资源清理工作。

与业务相关的细粒度任务适合首选HandlerInterceptor,

使用场景

鉴权,可以使用HandlerInterceptor但是Filter是更佳的选择。
审计日志,记录每一个请求。
Token解析或校验。
Handler执行时间统计。

Filter与Interceptor区别

1、拦截器是基于java的反射机制,使用代理模式,而过滤器是基于函数回调。

2、拦截器不依赖servlet容器,过滤器依赖于servlet容器。

3、拦截器只能对action起作用,而过滤器可以对几乎所有的请求起作用(可以保护资源)。

4、拦截器可以访问action上下文,堆栈里面的对象,而过滤器不可以。

5、执行顺序:过滤前-拦截前-Action处理-拦截后-过滤后。

作用域不同

  1. 过滤器依赖于servlet容器,只能在 servlet容器,web环境下使用
  2. 拦截器依赖于spring容器,可以在spring容器中调用,不管此时Spring处于什么环境

细粒度的不同

  1. 过滤器的控制比较粗,只能在请求进来时进行处理,对请求和响应进行包装
  2. 拦截器提供更精细的控制,可以在controller对请求处理之前或之后被调用,也可以在渲染视图呈现给用户之后调用

中断链执行的难易程度不同

  1. 拦截器可以 preHandle方法内返回 false 进行中断
  2. 过滤器就比较复杂,需要处理请求和响应对象来引发中断,需要额外的动作,比如将用户重定向到错误页面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值