过滤器和拦截器区别

各自实现:

过滤器一般继承Filter接口,并主要重写doFilter方法,如下:

public class Authfilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        log.info("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        // 业务代码
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        log.info("过滤器销毁");
    }

}

拦截器一般继承HandlerInterceptor接口,根据业务需要,重写各自方法,用的最多的便是preHandler方法,如下:

public class Interceptor implements HandlerInterceptor {

    // 在业务处理器处理请求之前被调用
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        return true;
    }
    // 在业务处理器处理请求完成之后,生成视图之前执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception{
    }
    // 在DispatcherServlet完全处理完请求之后被调用,可用于清理资源
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception{
    }
}

 

主要区别:

a、过滤器是基于函数回调机制实现,而拦截器是基于反射机制实现

-- 函数回调简单来说就是A在调用B的接口时,该接口中又调用了A的某个接口c,此时c则称为回调接口,过滤器正是基于该机制,FilterChain.doFilter(request,response)方法即回调方法,而拦截器则采用动态代理实现

b、过滤器依赖servlet容器,而拦截器不依赖

-- 因为过滤器是servlet规范规定的,只适用于web程序中,所以依赖servlet容器,而拦截器是在spring容器内的,是spring框架规定的

c、过滤器可以对所有请求起作用,而拦截器只能对action层/controller层请求起作用

-- 所有请求是指不管url正确与否都会进入到过滤器中,而action层请求则是我们事先定义好的那些请求

d、过滤器只能在servlet前后起作用,而拦截器能深入到方法前后、异常抛出前后等

-- 这也是由于两者所属的规范不同导致

e、拦截器可以获取IOC容器内的各个bean,因为它是一个spring的组件,归spring管理,所以能在拦截器内注入bean,而过滤器中则无法简单的通过注解的形式注入bean

-- 若想要在过滤器中使用某些类则可以通过某个单例类去获取,前提是要获取的那个类需事先在spring xml中通过<bean>标签注入

 

过滤器和拦截器的执行顺序:

过滤前 -> 拦截前 -> action处理 -> 拦截后 -> 过滤后

这里从网上找来一张图可能更直观一点,如下:

结合这张图的信息再顺便想一下SpringMVC的工作原理,有没有更深刻的理解?所以我们可以发现过滤器是请求在进入容器后,但进入servlet之前进行预处理,请求结束后同理,在servlet之后,返回前端之前进行后处理,因此过滤器包裹servlet,而servlet包裹拦截器,如下图:

 

SpringBoot过滤器不生效的常见原因:

1、未在过滤器类上加上@WebFilter注解,或者是该注解其下的filterName属性名首字母大写导致,需认真排查

2、未在启动类上标注扫描的过滤器的包路径,在启动类上加上该注解即可@ServletComponentScan(basePackages = "xxx.filter")

 

SpringBoot多过滤器如何配置其过滤顺序?

一个请求或响应可以被多个过滤器进行过滤,一般只有当这些过滤器过滤的url有重叠时并且有业务上需要指定顺序我们才需要进行配置顺序。网上常说的在过滤器类上加@Order()注解,实测是不生效的

首先最好新建一个配置类,用来控制所有过滤器,此时特定过滤器上的@WebFilter注解便能取消,配置类代码如下:

@Configuration
public class FilterOrder {

    @Bean
    public FilterRegistrationBean frontApiFilter() {
        FilterRegistrationBean filter = new FilterRegistrationBean();
        filter.setFilter(new Authfilter());
        filter.setName("frontApifilter");
        filter.addUrlPatterns("/notify/api/v1/*");
        // Order越小其执行越靠前
        filter.setOrder(2);
        return filter;
    }

    @Bean
    public FilterRegistrationBean openApiFilter() {
        FilterRegistrationBean filter = new FilterRegistrationBean();
        filter.setFilter(new OpenApiAuthFilter());
        filter.setName("openApiAuthFilter");
        filter.addUrlPatterns("/notify/openApi/*");
        filter.setOrder(1);
        return filter;
    }
}

通过设置Order属性即可指定过滤器的执行顺序了(注意这里说的是执行顺序而不是初始化顺序)

 

最后说一点,在spring构建的程序中,凡是过滤器能实现的,拦截器都能实现,具体使用哪一种也并无多大规定,反正你能实现需求就ok啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清茶_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值