Java 的过滤器Filter

(一)Filter 简介
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
  Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
  通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
  详细流程图如下:
  这里写图片描述

(二)Filter的工作原理
   Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
(1)调用目标资源之前,让一段代码执行。
(2)是否调用目标资源(即是否让用户访问web资源)。
(3) 调用目标资源之后,让一段代码执行。
  web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个
doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

(三)Filter开发流程步骤

第一步:编写java类实现Filter接口XssHttpFilter,并实现其doFilter方法。
第二步:实现web.xml文件中使用和元素对编写的filter类进行注册,并设置它所能拦截的资源。

第一步骤详细具体代码参考如下XssHttpFilter 实现接口Filter代码如下:

public class XssHttpFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}

第二步骤:web.xml配置过滤器引用:

<filter>
     <filter-name>xssHttpFilter</filter-name>
     <filter-class>com.utils.xss.XssHttpFilter</filter-class>
   </filter>
   <filter-mapping>
     <filter-name>xssHttpFilter</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>

(第四)Filter链

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter
方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

(第五)Filter生命周期

(1)Filter的创建
Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作,filter对象只会创建一次,init方法也只会执行一次。通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

(2)Filter的销毁
Web容器调用destroy方法销毁Filter。destroy方法在Filter的生命周期中仅执行一次。在destroy方法中,可以释放过滤器使用的资源。

(3)FilterConfig接口
用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了
filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
  String getFilterName():得到filter的名称。
  String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
  Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
  public ServletContext getServletContext():返回Servlet上下文对象的引用。
  

package com.yangcq.filter;  
import java.io.IOException;  
import java.util.Enumeration;  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
public class FilterTest implements Filter {  

    /* 过滤器初始化 
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 
     */  
    @Override  
    public void init(FilterConfig filterConfig) throws ServletException {  
        System.out.println("----过滤器初始化----");  
        /** 
         *  <filter> 
                  <filter-name>FilterTest</filter-name> 
                  <filter-class>com.yangcq.filter.FilterTest</filter-class> 
                  <!--配置FilterTest过滤器的初始化参数--> 
                  <init-param> 
                      <description>FilterTest</description> 
                      <param-name>name</param-name> 
                      <param-value>gacl</param-value> 
                  </init-param> 
                  <init-param> 
                      <description>配置FilterTest过滤器的初始化参数</description> 
                      <param-name>like</param-name> 
                      <param-value>java</param-value> 
                  </init-param> 
            </filter> 

             <filter-mapping> 
                  <filter-name>FilterDemo02</filter-name> 
                  <!--“/*”表示拦截所有的请求 --> 
                  <url-pattern>/*</url-pattern> 
             </filter-mapping> 
         */  
        //得到过滤器的名字  
        String filterName = filterConfig.getFilterName();  
        //得到在web.xml文件中配置的初始化参数  
        String initParam1 = filterConfig.getInitParameter("name");  
        String initParam2 = filterConfig.getInitParameter("like");  
        //返回过滤器的所有初始化参数的名字的枚举集合。  
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();  

        System.out.println(filterName);  
        System.out.println(initParam1);  
        System.out.println(initParam2);  
        while (initParameterNames.hasMoreElements()) {  
            String paramName = (String) initParameterNames.nextElement();  
            System.out.println(paramName);  
        }  
    }  

    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        System.out.println("FilterDemo02执行前!!!");  
        chain.doFilter(request, response);  //让目标资源执行,放行  
        System.out.println("FilterDemo02执行后!!!");  
    }  

    @Override  
    public void destroy() {  
        System.out.println("----过滤器销毁----");  
    }  
}  

(六)Filter的部署
(1)注册Filter
过滤器书写完毕后,需要在web.xml文件中进行注册,这样才能够被web服务器调用。举例

<filter>  
    <description>过滤器名称</description>  
    <filter-name>自定义的名字</filter-name>  
    <filter-class>com.yangcq.filter.FilterTest</filter-class>  
    <!--配置FilterTest过滤器的初始化参数-->  
    <init-param>  
        <description>配置过滤器的初始化参数</description>  
        <param-name>name</param-name>  
        <param-value>gacl</param-value>  
    </init-param>  
    <init-param>  
        <description>配置FilterTest过滤器的初始化参数</description>  
        <param-name>like</param-name>  
        <param-value>java</param-value>  
    </init-param>  
</filter>  

web.xml中

   <description>用于添加描述信息,该元素的内容可为空,        <description>可以不配置。
  <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
  <filter-class>元素用于指定过滤器的完整的限定类名。
  <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。在过滤器中,
可以使用FilterConfig接口对象来访问初始化参数。如果过滤器不需要指定初始化参数,那么<init-param>元素可以不配置。

(2)映射Filter

 <!--映射过滤器-->
   <filter-mapping>
       <filter-name>FilterDemo02</filter-name>
       <!--“/*”表示拦截所有的请求 -->
       <url-pattern>/*</url-pattern>
   </filter-mapping>
<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
  <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
  <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
  <servlet-name>指定过滤器所拦截的Servlet名称。
  <dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。如下:
<filter-mapping>
     <filter-name>testFilter</filter-name>
    <url-pattern>/index.jsp</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
 </filter-mapping>
<dispatcher> 子元素可以设置的值及其意义:

REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

### Java中的过滤器Filter)概念 在Java Web开发中,`javax.servlet.Filter` 接口允许开发者执行特定的任务,在请求到达Servlet之前或响应返回客户端之后。通过这种方式,可以在不修改现有代码的情况下增强功能[^3]。 ### 过滤器的主要作用 - **预处理请求**:可以对传入的HTTP请求进行加工处理,比如编码转换、日志记录等。 - **后置处理响应**:同样也可以操作即将发送给浏览器的数据流,如压缩HTML内容、设置Cache-Control头信息等。 - **权限控制**:检查用户身份验证状态或其他条件决定是否放行访问目标资源。 - **统一管理跨域资源共享(CORS)**:配置公共策略应用于多个端点之上。 ### 实现方式 要创建自定义过滤器,需编写一个实现了 `javax.servlet.Filter` 的类,并重写其中三个主要方法: #### 初始化阶段 ```java public void init(FilterConfig filterConfig) throws ServletException { // 可在此处获取初始化参数并完成必要的准备工作 } ``` 此部分通常用来加载配置项或是建立数据库连接池等工作;当Web应用启动时会调用一次init() 方法来进行初始化工作。 #### 执行逻辑 ```java public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest)request; HttpServletResponse httpResponse = (HttpServletResponse)response; String paramA = httpRequest.getParameter("paramName"); if ("ABC".equalsIgnoreCase(paramA)) { // 如果满足某些条件,则阻止后续的操作 httpResponse.getWriter().print("ParamA value is not allowed"); return; } // 继续沿链传递请求/响应对象至下一个元素(可能是另一个过滤器或者是最终的目的地servlet/jsp页面) chain.doFilter(request,response); } ``` 这段代码展示了如何拦截请求并对之加以判断,只有符合条件才会继续向下游转发。 #### 销毁清理 ```java public void destroy(){ // 清理资源,例如关闭数据库连接 } ``` 当服务器停止服务或者重新部署应用程序的时候会被触发destroy() 来释放占用资源。 为了使新构建好的过滤器生效,还需要将其注册到web.xml 文件里指定映射路径,亦可通过注解形式简化声明过程[@WebFilter]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值