过滤器和拦截器的区别

简介: Filter 也称为过滤器,基于Servlet实现,拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行,基于AOP思想,对方法进行增强。和servlet 中的过滤器类似,都是对用户请求进行处理。

什么是过滤器?


Filter 也称为过滤器,基于Servlet实现,过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet的工作原理是拦截配置好的客户端请求,然后对Request和Response进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。


什么是拦截器?


拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行,基于AOP思想,对方法进行增强。和servlet 中的过滤器类似,都是对用户请求进行处理。



他们有什么不同?


  1. 拦截器是基于Java的反射机制,而过滤器是基于函数回调;
  2. 拦截器不依赖servlet容器,过滤器依赖servlet容器;
  3. 拦截器只能对Controller 请求起作用,而过滤器则可以对几乎所有的请求起作用;
  4. 拦截器可以访问action上下文、堆栈里的对象,过滤器不能访问;
  5. 在action生命周期中,拦截器可以多次被调用,过滤器只能在容器初始化时被调用一次。


在springboot中使用拦截器和过滤器


使用过滤器,有两种方式


  1. 实现 Filter 类,重写其 doFilter 方法,注意这个类是 javax.servlet 包下的


@Slf4j
@Component
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        log.info("进入过滤器 MyFilter");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
  1. 注册


@Configuration
public class FilterConfig {
    @Autowired
    private MyFilter myFilter;
    @Bean
    public FilterRegistrationBean injectFilterOne() {
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(myFilter);
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("filter_one");
        // 优先级
        registrationBean.setOrder(1);
        return registrationBean;
    }
}
  1. 使用 @WebFilter 注解


@Slf4j
@WebFilter(filterName = "filter_two", urlPatterns = {"/*"})
public class MyFilter2 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        log.info("进入过滤器 MyFilter2");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
  1. 这种方式需要在启动类上扫描 @WebFilter注解,需要加上以下注解
    @ServletComponentScan(value = {"com.example.config.filter"})


使用拦截器


新建一个类实现 HandlerInterceptor 接口



@Component
@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("进入拦截器 MyIntercept,preHandle 方法 ");
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("进入拦截器 MyIntercept,postHandle 方法 ");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("进入拦截器 MyIntercept,afterCompletion 方法 ");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

注册


@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 拦截器拦截路径
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
    }
}


1. preHandle(......)方法:当url已经匹配到controller层中某个方法时,在方法执行前执行
它会决定是否放行,返回true,放行,返回false,不会执行
2.  postHandle(……) 方法:url 匹配到Controller 中的某个方法,且执行完了该方法,
但是在 DispatcherServlet 视图渲染之前执行。在这个方法中有个 ModelAndView 参数,可以在此做一些修改动作。
3. afterCompletion(……) 方法:在整个请求处理完成后(包括视图渲染)执行,
做一些资源的清理工作,这个方法只有在 preHandle(……) 被成功执行后并且返回true才会被执行。


过滤器和拦截器放在一起的执行结果:



2023-05-06 23:41:48.774  INFO 15484 --- [nio-8080-exec-2] com.example.config.filter.MyFilter       : 进入过滤器 MyFilter
2023-05-06 23:41:48.774  INFO 15484 --- [nio-8080-exec-2] com.example.config.filter.MyFilter2      : 进入过滤器 MyFilter2
2023-05-06 23:41:48.785  INFO 15484 --- [nio-8080-exec-2] c.e.config.interceptor.MyInterceptor     : 进入拦截器 MyIntercept,preHandle 方法 
2023-05-06 23:41:48.807  INFO 15484 --- [nio-8080-exec-2] c.e.config.interceptor.MyInterceptor     : 进入拦截器 MyIntercept,postHandle 方法 
2023-05-06 23:41:48.807  INFO 15484 --- [nio-8080-exec-2] c.e.config.interceptor.MyInterceptor     : 进入拦截器 MyIntercept,afterCompletion 方法


参考文章


  1. blog.csdn.net/K_520_W/art…
  2. www.cnblogs.com/wangms821/p…
目录
相关文章
|
数据库 开发者
Seata调用问题之全局异常捕获没法回滚如何解决
Seata是一款开源的分布式事务解决方案,旨在提供高效且无缝的分布式事务服务;在集成和使用Seata过程中,开发者可能会遇到不同的异常问题,本合集针对Seata常见异常进行系统整理,为开发者提供详细的问题分析和解决方案,助力高效解决分布式事务中的难题。
990 93
|
算法 安全 数据安全/隐私保护
DSA与RSA的区别、ECC(椭圆曲线数字签名算法(ECDSA))
DSA与RSA的区别、ECC(椭圆曲线数字签名算法(ECDSA))
1628 0
|
大数据 Linux 数据库
openEuler操作系统介绍
openEuler是一款开源免费的操作系统,由openEuler社区运作,支持多种处理器,适用于数据库、大数据、云计算等场景。它源自华为EulerOS,现分为创新版和LTS版,分别每半年和每两年发布一次。本课程以openEuler 20.03 LTS版为例,介绍其安装流程和环境准备。
1386 3
|
C#
45【软件技术基础】C#调用NPOI插件对EXCEL进行处理
NPOI插件进行EXCEL表格处理,不依赖第三方软件,功能强大,使用简便。 C#调用NPOI插件进行EXCEL单个表和文件夹中批量表的处理。
503 1
Java中的正则表达式详解
Java中的正则表达式详解
|
搜索推荐 数据安全/隐私保护
战斧指纹浏览器与IPXProxy海外代理IP配置详解
对于需要管理多个电商平台店铺的用户而言,战斧指纹浏览器提供了便捷的多账号隔离功能。跨境电商卖家要想在海外顺利的管理自己的店铺,还需要用到海外代理IP来实现IP隔离,确保店铺之间互相独立,不会受到其他店铺的牵连。下面以IPXProxy海外代理IP为例,给大家带来战斧指纹浏览器集成IPXProxy海外代理IP的详细指南。
734 0
|
Kubernetes 数据安全/隐私保护 Docker
如何利用k8s拉取私有仓库镜像
有时候远程仓库的镜像不一定可以拉取,所以私有仓库很重要。
|
Java 网络安全
springboot集成feign
springboot集成feign:如果觉得好用,不要忘记点赞关注加收藏哟!!!绝对干货
736 0
|
存储 关系型数据库 Java
技术经验解读:三种分布式事务LCN、Seata、MQ
技术经验解读:三种分布式事务LCN、Seata、MQ
712 0
|
域名解析 网络协议 安全
【域名解析DNS专栏】DNS-over-TLS与DNS-over-HTTPS:安全升级新标准
【5月更文挑战第26天】随着网络技术的发展,DNS协议面临安全挑战,DNS-over-TLS (DoT) 和 DNS-over-HTTPS (DoH) 作为解决方案出现,旨在通过加密增强隐私和安全。DoT使用TLS封装DNS查询,防止流量被窥探或篡改;DoH则利用HTTPS隐藏DNS查询。实施DoT需在客户端和服务器间建立TLS连接,DoH需DNS服务器支持HTTPS接口。这两种技术为网络安全提供支持,未来有望更广泛部署,提升网络环境的安全性。
1998 0