【JavaWeb】一文搞懂Java过滤器与拦截器的区别

简介: 【JavaWeb】一文搞懂Java过滤器与拦截器的区别

一、什么是过滤器与拦截器?


1.1 过滤器(Filter)


java过滤器指的是在java中起到过滤的作用的一个方法。可以在一个请求到达servlet之前,将其截取进行逻辑判断,然后决定是否放行到请求的servlet;也可以在一个response到达客户端之前,截取结果进行逻辑判断,然后决定是否允许返回给客户端。


filter(过滤器) 有如下几个种类(功能):


用户授权的filter:filter负责判断用户是否有权限请求该页面。

给予过滤判断日志的filter:截取某个用户在本网站上的所有请求。

记录轨迹负责解码的filter:规定处理本次请求的解码方式。

需要注意的是,一个filter过滤器可以加在多个servlet控制器上,当然多个filter过滤器也是可以加在一个servlet控制器上的。


由此也是可以看出来,我们使用filter往往是对一些公共的操作进行处理。例如:判断用户权限,解码本次请求等。还比如,我们的web应用中某些页面是需要用户登录后才能访问的,以往我们都是在每个servlet页面加上判断控制,导致代码冗余。有了filter,我们可以定义一个实现了filter的过滤器,让需要判断是否登录的页面都加上这么一个过滤器,可以大大降低代码的冗余程度


1.2 拦截器(Interceptor)


java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。


作用域:动态拦截Action调用的对象(也就是我们的controller层)


在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。 由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。


二、过滤器与拦截器的区别


2.1 实现原理不同


过滤器的实现基于回调函数

拦截器基于Java的反射机制【动态代理】实现。


2.2 使用范围不同


过滤器是Servlet的规范,需要实现javax.servlet.Filter接口,Filter使用需要依赖于Tomcat等容器。

拦截器是Spring组件,定义在org.springframework.web.servlet包下,由Spring容器管理【又有更加丰富的生缪那个周期处理方法,细粒度,且能够使用Spring中的资源】,不依赖Tomcat等容器。


2.3 触发时机不同


过滤器:对请求在进入后Servlet之前或之后进行处理。

拦截器:对请求在handler【Controller】前后进行处理。


2.4 执行顺序不同


执行顺序 :Filter 处理中 -> Interceptor 前置 -> 我是controller -> Interceptor 处理中 -> Interceptor 处理后


当有两个过滤器或拦截器时:


过滤器:

每一次都将chain对象传入,达到最后接口回调的效果,类似函数的堆栈调用。


拦截器:

preHandle1 -> preHande2 -> 【Controller】 -> postHandle2 -> postHandle1 -> afterCompletion2 -> afterComplention1


preHandle按照注册顺序,后两个与注册顺序相反。


一个拦截器的preHandle为false,则之后的所有拦截器都不会执行。

一个拦截器的preHandle为true,则这个拦截器的triggerAfterCompletion一定会执行。

只有所有的拦截器preHandler都为true,也就是正常执行,postHandle才会执行。

2.5 控制执行顺序方式不同

实际开发过程中,会出现多个过滤器或拦截器同时存在的情况,不过,有时我们希望某个过滤器或拦截器能优先执行,就涉及到它们的执行顺序。


过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行。


@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyFilter2 implements Filter {}


拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。


@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(3);
    }


三、过滤器与拦截器的实现


3.1 过滤器实现


过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。


init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。

doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次


@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter 前置");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter 处理中");
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
        System.out.println("Filter 后置");
    }
}



3.2 拦截器实现


拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor, 一个请求也可以触发多个拦截器 ,而每个拦截器的调用会依据它的声明顺序依次执行。首先编写一个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,看到HandlerInterceptor 接口中也定义了三个方法。


preHandle() :这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。

postHandle():只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。 有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。

afterCompletion():只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。


@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor 前置");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor 处理中");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor 后置");
    }
}


将自定义好的拦截器处理类进行注册,并通过addPathPatterns、excludePathPatterns等属性设置需要拦截或需要排除的 URL。


@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");
    }
}
相关文章
|
11天前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
65 1
|
1月前
|
Java 测试技术
Java浮点类型详解:使用与区别
Java中的浮点类型主要包括float和double,它们在内存占用、精度范围和使用场景上有显著差异。float占用4字节,提供约6-7位有效数字;double占用8字节,提供约15-16位有效数字。float适合内存敏感或精度要求不高的场景,而double精度更高,是Java默认的浮点类型,推荐在大多数情况下使用。两者都存在精度限制,不能用于需要精确计算的金融领域。比较浮点数时应使用误差范围或BigDecimal类。科学计算和工程计算通常使用double,而金融计算应使用BigDecimal。
792 102
|
2月前
|
存储 缓存 人工智能
Java int和Integer的区别
本文介绍了Java中int与Integer的区别及==与equals的比较机制。Integer是int的包装类,支持null值。使用==比较时,int直接比较数值,而Integer比较对象地址;在-128至127范围内的Integer值可缓存,超出该范围或使用new创建时则返回不同对象。equals方法则始终比较实际数值。
111 0
|
2月前
|
安全 算法 Java
Java 中 synchronized 与 AtomicInteger 的区别
在Java多线程编程中,`synchronized`和`AtomicInteger`均用于实现线程安全,但原理与适用场景不同。`synchronized`是基于对象锁的同步机制,适用于复杂逻辑和多变量同步,如银行转账;而`AtomicInteger`采用CAS算法,适合单一变量的原子操作,例如计数器更新。二者各有优劣,应根据具体需求选择使用。
85 0
|
3月前
|
算法 Java 数据库连接
Java 与 C++ 区别深入剖析及应用实例详解
本文深入剖析了Java和C++两种编程语言的区别,从编译与执行机制、面向对象特性、数据类型与变量、内存管理、异常处理等方面进行对比,并结合游戏开发、企业级应用开发、操作系统与嵌入式开发等实际场景分析其特点。Java以跨平台性强、自动内存管理著称,适合企业级应用;C++则因高性能和对硬件的直接访问能力,在游戏引擎和嵌入式系统中占据优势。开发者可根据项目需求选择合适语言,提升开发效率与软件质量。附面试资料链接:[点此获取](https://pan.quark.cn/s/4459235fee85)。
298 0
|
3月前
|
存储 Java C语言
Java List 复制:浅拷贝与深拷贝方法及区别
我是小假 期待与你的下一次相遇 ~
325 1
|
4月前
|
Java
Java 中 Exception 和 Error 的区别
在 Java 中,`Exception` 和 `Error` 都是 `Throwable` 的子类,用于表示程序运行时的异常情况。`Exception` 表示可被捕获和处理的异常,分为受检异常(Checked)和非受检异常(Unchecked),通常用于程序级别的错误处理。而 `Error` 表示严重的系统级问题,如内存不足或 JVM 错误,一般不建议捕获和处理。编写程序时应重点关注 `Exception` 的处理,确保程序稳定性。
115 0
|
XML Java 数据格式
java WebService CXF Spring 自定义拦截器 附实例源码
java WebService CXF Spring 自定义拦截器 附实例源码
261 0
java WebService CXF Spring 自定义拦截器 附实例源码
|
XML Java Apache
java WebService CXF Spring 自定义拦截器 附实例源码
java WebService CXF Spring 自定义拦截器 附实例源码
287 0
java WebService CXF Spring 自定义拦截器 附实例源码
|
11天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案