Servlet过滤器详解

简介: 系列

日常生活里,自来水都是经过一层层的过滤处理才达到食用标准的,每一层过滤都起到一种净化的作用,今天所讲Servlet过滤器与自来水被过滤的原理相似
自来水

1 定义

Servlet过滤器和 Servlet 很类似,注意的是它有 拦截客户端请求的用法,Servlet过滤器可以改变请求中的内容,满足实际开发的需要。

开发来讲,过滤器实质上是在Web应用服务器里面的一个Web组件,目的用在拦截客户端(浏览器)与目标资源的请求,并把这些请求进行一定过滤处理在发给目标资源:
1

看出,Web容器部署过滤器后,不仅客户端发送的请求会经过过滤器的处理,要不要返回呢?请求的回应信息也同样要经过过滤器。

如果一个Web应用中使用一个过滤器不能解决实际的业务需求,那可以部署多个过滤器对业务请求多次处理,这样做就组成一个过滤器链,Web容器在处理过滤器时,将被过滤器的先后顺序对请求进行处理:
2

Web窗口中部署过滤器链,那么请求会一次按照过滤器顺序进行处理,在第一个过滤器处理一请求后,会传递给第二个过滤器进行处理,依次类推,传递到最后一个过滤器为止,再将请求交给目标资源进行处理,目标资源在处理经过过滤的请求后,其回应信息再从最后一个过滤器依次传递到第一个过滤器,最后传送到客户端;

2 过滤器核心对象

过滤器对象放置在 javax.servlet 包中,叫做 Filter, 是个接口,与过滤器相关的对象还有 FilterConfig对象 与 FilterChain对象,这两个也同样是接口对象,位于 javax.servlet 包中,分别作为过滤器的配置对象与过滤器的传递工具。在实际开发,定义过滤器对象只需要直接或间接地实现 Filter接口即可。下图的MyFilter1过滤器与MyFilter2过滤器,而 FilterConfig对象FilterChain对象 用在过滤器的相关操作:
3

Filter接口

每个过滤器对象只直接或间接地实现 Filter接口,在Filter接口中定义了3个方法,分别是 init(),doFilter()和destroy(),方法及说明如表:

方法 声明
public void init(FilterConfig filterConfig) throws ServletException 过滤器初始化方法,该方法在过滤器初始化时调用
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 对请求进行过滤处理
public void destroy() 销毁方法,以便释放资源

FilterConfig接口

Servlet容器进行实现,主要是获取过滤器中的配置信息,其方明及说明如表:

方法 说明
public String getFilterName() 用于获取过滤器的名字
public ServletContext getServletContext() 获取Servlet上下文
public String getInitParameter(String name) 获取过滤器的初始化参数值
public Enumeration getInitParameterNames() 获取过滤器的所有初始化参数

FilterChain接口

它由Servlet容器进行实现,在这个接口中一个方法,其方法声明:
public void doFilter(ServletRequest request, ServletResponse response)throws IOException,ServletException 该方法将过滤的请求传给下一个过滤器,如果此过滤器已经是过滤器链中的最后一个过滤器,那么,请求传送给目标资源。

过滤器创建于配置

创建一个过滤器对象需要实现 javax.serjavax.servlet.Filter接口,下面演示过滤器的创建:

创建名称为 MyFilter的过滤器对象,其代码如下:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servletFilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
* 过滤器
*/
public class MyFilter implements Filter{
       //初始化方法
       public void init(FilterConfig fConfig) throws ServletException{
       //初始化处理
       }
       //过滤处理方法
       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletEXception {
       //过滤处理
       chain.doFilter(request, response);
       }
       //销毁方法
       public void destroy(){
       //释放资源
       }     
}

过滤器的init()对过滤器的初始化进行处理,destroy()是过滤器的销毁方法,主要是释放资源,对于过滤器处理的业务需要编写到doFilter()里面,在请求过滤需调用chain参数的doFilter()将请求向下传给下一过滤器或目标资源:

使用过滤器并不一定要将请求向下传递到下一过滤器或目标资源,如果业务逻辑需要,也可以在过滤处理后,直接回应客户端;

过滤器与Servlet十分相似,在创建后同样对其配置,过滤器的配置主要分为两个步骤,分别在声明过滤器对象和创建过滤器映射,创建名为MyFilter的过滤器对象:

<!- 过滤器声明 ->
<filter>
      <!- 过滤器的名称 ->
      <filter-name>MyFilter</filter-name>
      <!- 过滤器的完整类名 ->
      <filter-class>com.lyq.Myilter</filter-class>
</filter>
<!- 过滤器映射 ->
<filter-mapping>
    <!- 过滤器名称 ->
    <filter-name>MyFilter</filter-name>
    <!-- 过滤器 URL映射 ->
    <url-pattern>/MyFilter</filter-name>
    <!- 过滤器URL映射 ->
    <url-pattern>/MyFilter</url-pattern>
</filter-mapping>    
      

< filter>标签用在声明过滤器对象,这个标签中必须配置两个子元素,分别是过滤器的名称过滤器完整类名,其中< filter-name>定义过滤器的名称,< filter-class>指定过滤器的完整类名。

< filter-mapping>标签用于创建过滤器的映射,它的主要作用是指定Web应用中,哪些URL应用哪一个过滤器进行处理,在< filter-mapping>标签里面需要你自己指定过滤器应用的URL。

< filter>标签中的< filter-name>可以是自定义的名称,而< filter-mapping>标签中的< filter-name>是指定已定义的过滤器名称,没法改变。它需要和< filter>标签中的< filter-name>一一对应;

我们试着创建一个过滤器,完成网站访问计数器的功能,在web.xml文件的配置里,将网站访问量的初始值设置为5000。

新建名称是CountFilter的类,该类实现 javax.servlet.Filter接口,它是个过滤器对象,通过该过滤器实现统计网站访问人数,关键代码:

  
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
  
public class CountFilter implements Filter{
  
  //来访数量
  private int count;
  @Override
  public void init(FilterConfig filterConfig) throws ServletException{
              String param = filterConfig.getInitParameter("count");
        count++;
    
  //将ServletRequest 转换成 HttpServletRequest
  HttpServletRequest req = (HttpServletRequest)request;
  
  //获取ServletContext
  ServletContext context = req.getSession.getServletContext();
  context.setAttribute("count", count);
  chain.doFilter(request, response);
}
  
  @Override
  public void destroy(){
  
  }
}
  

在ComFiler类中,包含一个成员变量 count,用于记录网站访问人数,该变量在过滤器的初始化方法init() 中被赋值,它的初始值通过FilterConfig对象读取配置文件中的初始化参数就可以得到;

计数器 count变量的值在CountFilter类的 doFilter()中递增, 因为客户端在请求服务器中的Web应用时侯,过滤器拦截请求通过 doFilter()方法进行过滤处理,所以当client请求Web应用时,计数器 ount的值将加1, 为了能够访问计数器中的值,实例中我们把它放置在 Servlet 上下文中,Servlet 上下文对象通过将 ServletRequest 转换为 HttpServletRequest对象后获取。

写过滤器对象需要我们实现 javax.servlet.Filter接口,实现该接口后需要对 Filter对象的3个方法进行实现,在这3个方法中,除了 doFilter()方法外,如果在业务逻辑中不涉及初始化方法 init()与销毁方法 destroy(), 可以不编写任何代码对其进行 空实现,如实例中的 destroy()方法。

配置已创建的 CountFilter对象,此操作通过配置web.xml文件进行实现。

<filter>  
  <filter-name>CountFilter</filter-name>
  <filter-class>com.lyq.CountFilter</filter-class>
  <init-param>
        <param-name>count</param-name>
        <param-value>5000</param-value>
    </init-param>
</filter>
        
  <filter-mapping>
        <filter-name>CountFilter</filter-name>
         <url-pattern>/index.jsp</url-pattern>
  </filter-mapping> 
  

CountFilter对象的配置主要通过声明过滤器及创建过滤器的映射进行实现,其中声明过滤器要通过 < filter>标签进行实现。在声明过程中,实例用< init-param>标签配置过滤器的初始化参数,初始化参数的名称为count,参数值为5000;

如果直接对过滤器对象的成员变量进行赋值,那在过滤器被编译后将不可修改,所以,实例中将过滤器对象中的成员变量定义为过滤器的初始化参数,提高了代码的灵活性;

创建程序中的首页index.jsp页面,在该页面中通过JSP内置对象Application获取计数器的值。关键代码如下:

  
<body>
    <h2>
      欢迎光临, <br>
      你是本站的第【
      <%=application.getAttribute("count") %>
        】位访客!
        </h2>
</body>
  

因为在web.xml中将计数器的初始值设置为 5000,所以实例运行后,计数器的数值变为大于5000的数,在多次刷新页面后,实例运行结果:

相关文章
|
3月前
|
JavaScript Java 容器
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
本文简要回顾了Servlet过滤器Filter的概念和使用,通过实例演示了如何创建过滤器以过滤请求字符编码,并解释了在web.xml中配置过滤器时使用`/`、`/*`和`/**`的区别。
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
|
4月前
|
存储 前端开发 Java
servlet过滤器--使用过滤器统计网站访问人数的计数(注解形式)
该文章展示了如何使用Servlet过滤器(Filter)通过注解方式创建一个网站访问人数统计功能,通过`@WebFilter`注解定义过滤器及其URL模式,并在`doFilter`方法中实现计数逻辑,将访问次数存储在`ServletContext`中,最后在JSP页面展示访问人数。
servlet过滤器--使用过滤器统计网站访问人数的计数(注解形式)
|
4月前
|
C# 数据可视化 开发者
WPF开发者福音:深度解析OxyPlot与LiveCharts图表库,轻松实现数据可视化不再是难题!
【8月更文挑战第31天】在WPF应用中,数据可视化对提升用户体验至关重要。本文介绍并演示了两种流行图表库OxyPlot和LiveCharts的集成与使用方法。OxyPlot是一款适用于.NET应用的开源图表库,提供多种图表类型,易于集成。LiveCharts则以其丰富的图表类型和动画效果,特别适合实时数据展示。通过具体代码示例,本文展示了如何利用这两种图表库创建折线图和柱状图,并详细说明了安装和配置步骤。希望本文能帮助开发者在WPF应用中轻松实现高效、美观的数据可视化。
238 0
|
4月前
|
监控 前端开发 Java
揭秘Web开发神器:Servlet、过滤器、拦截器、监听器如何联手打造无敌博客系统,让你的用户欲罢不能!
【8月更文挑战第24天】在Java Web开发中,Servlet、过滤器(Filter)、拦截器(Interceptor,特指Spring MVC中的)及监听器(Listener)协同工作,实现复杂应用逻辑。以博客系统为例,Servlet处理文章详情请求,过滤器(如LoginFilter)检查登录状态并重定向,Spring MVC拦截器(如LoggingInterceptor)提供细粒度控制(如日志记录),监听器(如SessionListener)监控会话生命周期事件。这些组件共同构建出高效、有序的Web应用程序。
42 0
|
7月前
|
容器
Servlet 教程 之 Servlet 编写过滤器 6
该教程介绍了如何在Servlet中编写过滤器。可以创建多个过滤器,如AuthenFilter和LogFilter,并通过不同的映射进行配置。过滤器的应用顺序由web.xml中filter-mapping的顺序决定,可通过调整顺序改变过滤器执行的先后。
36 3
|
7月前
|
Java 容器
Servlet 教程 之 Servlet 编写过滤器 2
Servlet过滤器教程:实现Filter接口,包含3个核心方法。1) doFilter用于实际过滤,处理匹配URL的请求,调用FilterChain处理后续过滤。2) init方法在应用启动时被调用,初始化filter,从FilterConfig获取配置信息。3) destroy方法在过滤器销毁前执行,释放资源。
37 2
|
7月前
|
Java
Servlet 教程 之 Servlet 编写过滤器 3
`LogFilter` 是一个 Servlet 过滤器示例,它打印网站名称并传递请求至过滤链。当与 `DisplayHeader` Servlet(显示 HTTP 头信息)配合使用时,提供基础过滤器概念的理解。过滤器在请求处理前可添加额外功能或修改输入,而 `doGet` 方法则用于响应 GET 请求,展示请求头信息。
27 2
|
7月前
|
XML 数据格式
Servlet 教程 之 Servlet 编写过滤器 4
在Servlet教程中,学习如何编写过滤器。在`web.xml`配置文件中,创建一个名为`LogFilter`的过滤器,类为`com.baidu.test.LogFilter`,设置初始化参数`Site`为`百度`。将过滤器映射到`/*`,确保所有请求都会经过此过滤器。同时定义了一个名为`DisplayHeader`的Servlet,映射到`/TomcatTest/DisplayHeader`路径。
29 1
|
7月前
|
XML Java 数据安全/隐私保护
Servlet 教程 之 Servlet 编写过滤器 1
Servlet过滤器用于动态拦截请求和响应,实现如身份验证、数据压缩、日志记录等多种功能。它们可附加于Servlet、JSP或HTML,按web.xml中配置的顺序执行。Web容器启动时会根据部署描述符创建过滤器实例。
39 2
|
7月前
|
容器
Servlet 教程 之 Servlet 编写过滤器 7
Servlet教程讲解如何编写过滤器。在`web.xml`中,`&lt;filter&gt;`定义过滤器,`&lt;filter-name&gt;`和`&lt;filter-class&gt;`分别设定名称和类。`&lt;init-param&gt;`配置初始化参数。`&lt;filter-mapping&gt;`指定过滤器作用的资源,可通过`&lt;servlet-name&gt;`或`&lt;url-pattern&gt;`定义。`&lt;dispatcher&gt;`定义过滤器触发时机,如REQUEST、INCLUDE、FORWARD和ERROR,控制过滤器何时拦截资源调用。
37 0