聊聊java 过滤器、监听器、拦截器的区别(终结篇)

yizhihongxing

下面是详细讲解“聊聊java 过滤器、监听器、拦截器的区别(终结篇)”的完整攻略。

什么是过滤器、监听器和拦截器?

在 Java Web 开发中,过滤器(Filter)、监听器(Listener)、拦截器(Interceptor)都是用来对 HTTP 请求进行处理和过滤的技术手段。

过滤器(Filter)

过滤器(Filter)是在 Servlet 中用来对请求和响应进行预处理和后处理的简单对象,用于统一修改请求/响应属性或处理请求/响应。Filter 通常用于对请求进行过滤处理,比如编码转换、HTTP 认证等。

监听器(Listener)

监听器(Listener)是在 Servlet 中用来监听 Web 应用程序中某些对象和事件状态的接口,以触发相应的事件处理器对其作出响应。比如,我们可以监听会话的创建和销毁事件,对用户的会话进行管理。

拦截器(Interceptor)

拦截器(Interceptor)是 Spring Framework 提供的,是一种更强大的对请求的拦截和修改的机制,也用于统一地修改请求/响应属性或处理请求/响应,但比 Filter 更加强大。拦截器具有链式的特点,可以自由控制拦截顺序,也可以中断后面的拦截器或处理器。拦截器可以用于各种场景,比如拦截非法请求、记录请求日志、性能监控等。

过滤器、监听器、拦截器的区别

处理范围不同

过滤器是处理请求和响应,监听器是监听对象、资源、事件等的变化,拦截器是在控制器(Controller)前后进行拦截,处理请求和响应。

触发时机不同

过滤器是在请求被 Servlet 前处理,响应处理结束后才被调用,如下图:

         ----------       ----------       ----------
Request |  Filter1 |---->|  Filter2 |---->|  Filter3 |---->| Servlet |
         ----------       ----------       ----------

         ----------       ----------       ----------
Response|  Filter3 |<----|  Filter2 |<----|  Filter1 |<----| Servlet |
         ----------       ----------       ----------

监听器是在对象的生命周期中监听对象的某些状态,如下图:

              ------------------ 
Web Container |  Object  | Event |
              ------------------   
                  |   /\   | ^    
                  |   |    | |    
                  |   |    | |    
                  v   |    | |    
              ------------------- 
Application   |   Listener          |
              ------------------- 

拦截器是在请求到达控制器之前或者响应返回浏览器之前进行拦截或者修改,如下图:

                  ------------ 
     Inbound --->|Interceptors|---+     
                  ------------    | 
                        |         |Before the
                        |         |Controller
                        v         | 
                  ------------ 
              --->| Controller |
                  ------------  
                        |         |
                        v         |After the
                  ------------    |Controller
                 |Interceptors|
                  -------------
                        |         |
                        v           Outbound
                 ------------
              <---|Interceptors|<---
                 ------------    

配置方式不同

Filter 配置在 web.xml 中:

<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Listener 配置在 web.xml 中:

<listener>
    <listener-class>com.example.MyListener</listener-class>
</listener>

Interceptor 配置在 Spring 的配置文件中:

<mvc:interceptors>
    <bean class="com.example.MyInterceptor"/>
</mvc:interceptors>

示例说明

示例 1:使用过滤器统一处理编码问题

在很多 Web 应用中,中文字符集的编码很容易出现问题,如果没能正确处理会出现乱码问题,这时可以使用过滤器来统一处理编码问题,比如下面的代码:

public class EncodingFilter implements Filter {

    private String encoding;

    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setContentType("text/html;charset=" + encoding);
        chain.doFilter(request, response);
    }

    public void destroy() {
    }
}

在 web.xml 中配置过滤器:

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.example.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这样,在所有的请求中,请求参数的编码方式都会被统一设置成 UTF-8。

示例 2:使用拦截器记录请求日志

在许多场景中,需要记录请求日志,比如,记录请求的 URL、请求方法、请求参数、请求时间等,这时候我们可以使用拦截器来实现,比如下面的代码:

public class LogInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("请求: {}, 方法: {}", request.getRequestURL(), request.getMethod());
        logger.info("IP地址: {}", request.getRemoteAddr());
        logger.info("请求参数: {}", JSONObject.toJSONString(request.getParameterMap()));
        logger.info("请求时间: {}", LocalDateTime.now());
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

在 Spring 的配置文件中配置拦截器:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.example.LogInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

这样,在所有的请求前,都会先记录请求日志,并打印到日志文件中。

以上就是关于“聊聊java 过滤器、监听器、拦截器的区别(终结篇)”的全部内容。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:聊聊java 过滤器、监听器、拦截器的区别(终结篇) - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • AngularJS递归指令实现Tree View效果示例

    下面就详细讲解一下“AngularJS递归指令实现Tree View效果示例”的攻略。 1. 背景介绍 Tree View,即树形视图,是一种常用的数据展示方式,通常用于展示多层级关联数据。在Web前端开发中,我们通常使用AngularJS来构建复杂的Web应用程序。AngularJS提供了递归指令来实现树形组件的开发。下面,我们就来看一下如何使用递归指令来…

    other 2023年6月27日
    00
  • 网页导航栏html+css的代码实现

    网页导航栏HTML+CSS的代码实现 网页导航栏是网站的重要组成部分之一,它可以为用户提供网站的主要功能和导航链接。在本文中,我们将介绍如何使用HTML和CSS代码实现网页导航栏。 HTML代码实现 首先,我们来看一下网页导航栏的HTML代码实现。以下是一个基本的HTML导航栏结构: <nav> <ul> <li><…

    其他 2023年3月28日
    00
  • linux就业技术指导(五):linux运维核心管理命令详解

    Linux就业技术指导(五):Linux运维核心管理命令详解 Linux运维是Linux系统管理的重要组成部分,掌握Linux运维核心管理命令对于Linux系统管理员来说非常重要。本文将详细讲解Linux运维核心管理命令,并提供两个示例说明。 1. 系统管理命令 1.1 top命令 top命令可以实时监控系统的运行状态,包括CPU、内存、进程等信息。可以使用…

    other 2023年5月9日
    00
  • C++内存模型与名称空间概念讲解

    C++内存模型与名称空间概念讲解 内存模型 C++内存模型是指C++程序中变量的存储和访问方式。了解内存模型对于理解C++程序的执行过程和解决多线程并发访问问题非常重要。 C++内存模型主要包括以下几个方面: 栈(Stack):栈是用于存储局部变量和函数调用信息的一块内存区域。每当函数被调用时,栈会分配一块内存用于存储函数的局部变量和返回地址。当函数执行完毕…

    other 2023年8月15日
    00
  • C++中构造函数重载

    C++中构造函数重载 在C++程序中,构造函数相当于一个类的初始化操作,用于初始化对象的数据成员。当一个类中有多个构造函数时,我们称为“构造函数重载”。 通过构造函数重载,我们可以为对象提供不同的初始化方式,以满足不同的需求。 构造函数重载的定义 构造函数重载的定义与函数重载类似,它可以拥有多个构造函数,只要它们的参数列表不同即可。 class MyClas…

    other 2023年6月26日
    00
  • react自动化构建路由的实现

    React自动化构建路由的实现攻略 React是一个流行的JavaScript库,用于构建用户界面。在React应用中,路由是一个重要的概念,用于管理不同页面之间的导航和状态。本攻略将详细介绍如何使用React自动化构建路由。 步骤1:安装所需的依赖 首先,我们需要安装React Router库,它是React应用中最常用的路由库。可以使用以下命令来安装Re…

    other 2023年7月28日
    00
  • C语言实现链表与文件存取的示例代码

    下面我将详细讲解C语言实现链表与文件存取的示例代码的完整攻略。 链表的实现 创建链表 首先我们需要创建链表,在C语言中,链表是由节点(node)组成的,每个节点包含两个部分:一个是数据部分(data),另一个是指向下一个节点的指针(next)。我们可以使用结构体来定义一个节点: typedef struct Node { int data; struct N…

    other 2023年6月27日
    00
  • 解决内存不足妙方

    解决内存不足妙方攻略 1. 释放内存空间 当内存不足时,首先要考虑的是释放已占用的内存空间。以下是一些常见的方法: 关闭不必要的程序和进程:打开任务管理器(Windows)或活动监视器(Mac),查看哪些程序和进程占用了大量的内存资源。关闭不必要的程序和进程可以释放内存空间。 清理临时文件:临时文件是一些临时存储的文件,它们可能占用了大量的内存空间。使用系统…

    other 2023年8月1日
    00
合作推广
合作推广
分享本页
返回顶部