zoukankan      html  css  js  c++  java
  • Java Servlet Filter

      做web开发的人对于Filter应该不会陌生,一直在很简单的使用,但是一直没有系统的总结一下,随着年纪的慢慢长大,喜欢总结一些事情,下面说说我对Filter的理解,官方给出的Filter的定义是在请求一个资源或者从一个资源返回信息的时候执行过滤操作的插件。我们使用过滤起最多的场景估计就是在请求和返回时候的字符集转换,或者权限控制,比如一个用户没有登录不能请求某些资源。下面看一下Filter的集中类型:

    • Authentication Filters 
    • Logging and Auditing Filters
    • Image conversion Filters
    • Data compression Filters 
    • Encryption Filters 
    • Tokenizing Filters
    • Filters that trigger resource access events
    • XSL/T filters 
    • Mime-type chain Filter 

         Filters是在web.xml中配置的插件,Servlets和Filters相互没有依赖,如果通过编辑web.xml来添加和删除过滤器。

       实现过滤器非常简单,只需要实现javax.servlet.Filter接口,就可以实现一个过滤器,Filter接口定义的方法如下:

    • void init(FilterConfig filterConfig))--在filter被加载到service中的时候被container调用,Servlet container实例化完filter以后立即调用Filter的init方法,init方法中的工作必须在执行过滤过滤任务之前正确的完成。

        在以下情况下web container不能把filter加载到service中: 

      • 抛出ServletException异常。
      • 在container定义的时间内没有返回。
    • void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)--Filter中的doFilter方法在每次request/response时候会被container调用,能够传递到doFilter中的request或者response可以传递到Filter环中的下一个环节。 此时的Filter在设计模式中被称作责任链模式结构,这里面抽象处理者的角色就是javax.servlet.Filter这个接口,注册的所有Filter是具体的处理者,在doFilter方法中实现具体处理逻辑,在这里面责任链是一条直线,构成这条直线的就是所有注册的Filter。
    • destroy--当filter从service中移除的时候,container调用destroy方法,通过调用这个方法,释放Filter所占有的系统资源。

         如何在web.xml中配置Filter

    复制代码
    1 <filter>
    2     <display-name>EcodingFilter</display-name>
    3     <filter-name>EcodingFilter</filter-name>
    4     <filter-class>org.nb.filter.EnCodeFilter</filter-class>
    5     <init-param>
    6         <param-name>EncodeCoding</param-name>
    7         <param-value>UTF-8</param-value>
    8     </init-param>
    9 </filter>
    复制代码

         我们可以使用如下方法来给Filter匹配指定的servlet 资源或者url-pattern:

    1 <filter-mapping>
    2     <filter-name>EcodingFilter</filter-name>
    3     <servlet-name>*</servlet-name>
    4     <url-pattern>*</url-pattern>
    5 </filter-mapping>

         在这里需要注意的是,在给servlet注册filter环,container首先处理的是url-patterns,然后才处理servlet-names,所以如果要对filter的执行顺序有要求,那么在此需要注意。下面我们创建一个web工程,来实践一下Filter:

    web.xml内容:

    复制代码
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xmlns="http://java.sun.com/xml/ns/javaee"
     4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     5     version="3.0">
     6     <display-name>FilterTest</display-name>
     7     <welcome-file-list>
     8         <welcome-file>index.html</welcome-file>
     9     </welcome-file-list>
    10     <filter>
    11         <display-name>EcodingFilter</display-name>
    12         <filter-name>EcodingFilter</filter-name>
    13         <filter-class>org.nb.filter.EnCodeFilter</filter-class>
    14         <init-param>
    15             <param-name>EncodeCoding</param-name>
    16             <param-value>UTF-8</param-value>
    17         </init-param>
    18     </filter>
    19     <filter-mapping>
    20         <filter-name>EcodingFilter</filter-name>
    21         <servlet-name>hello</servlet-name>
    22         <url-pattern>*</url-pattern>
    23     </filter-mapping>
    24     <servlet>
    25         <servlet-name>hello</servlet-name>
    26         <servlet-class></servlet-class>
    27     </servlet>
    28     <servlet-mapping>
    29         <servlet-name>hello</servlet-name>
    30         <url-pattern>/*</url-pattern>
    31     </servlet-mapping>
    32 </web-app>
    复制代码

    HelloServlet.java内容:

    复制代码
     1 package org.nb.action;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.annotation.WebServlet;
     8 import javax.servlet.http.HttpServlet;
     9 import javax.servlet.http.HttpServletRequest;
    10 import javax.servlet.http.HttpServletResponse;
    11 
    12 @WebServlet("/helloServlet")
    13 public class HelloServlet extends HttpServlet {
    14     private static final long serialVersionUID = 1L;
    15 
    16     protected void doPost(HttpServletRequest request,
    17             HttpServletResponse response) throws ServletException, IOException {
    18         PrintWriter out = response.getWriter();
    19         out.println("<font color=red>Hello.</font>");
    20     }
    21 }
    复制代码

    EnCodeFilter.xm内容:

    复制代码
     1 package org.nb.filter;
     2 
     3 import java.io.IOException;
     4 import java.util.Enumeration;
     5 import java.util.HashMap;
     6 import java.util.Map;
     7 
     8 import javax.servlet.Filter;
     9 import javax.servlet.FilterChain;
    10 import javax.servlet.FilterConfig;
    11 import javax.servlet.ServletException;
    12 import javax.servlet.ServletRequest;
    13 import javax.servlet.ServletResponse;
    14 
    15 public class EnCodeFilter implements Filter {
    16 
    17     Map<String, String> params = new HashMap<String, String>();
    18 
    19     @Override
    20     public void destroy() {
    21         System.out.println("EncodeFilter destroy");
    22     }
    23 
    24     @Override
    25     public void doFilter(ServletRequest request, ServletResponse response,
    26             FilterChain chain) throws IOException, ServletException {
    27         String encodeCoding = params.get("EncodeCoding");
    28         request.setCharacterEncoding(encodeCoding);
    29         response.setCharacterEncoding(encodeCoding);
    30         chain.doFilter(request, response);
    31         System.out.println("EncodeFilter doFilter");
    32     }
    33 
    34     @Override
    35     public void init(FilterConfig cfg) throws ServletException {
    36         Enumeration<String> names = cfg.getInitParameterNames();
    37         while (names.hasMoreElements()) {
    38             String name = names.nextElement();
    39             params.put(name, cfg.getInitParameter(name));
    40         }
    41         System.out.println("EncodeFilter init");
    42     }
    43 
    44 }
    复制代码

    在tomcat启动的时候Console输出的内容:

    复制代码
    三月 24, 2014 5:56:12 下午 org.apache.catalina.core.AprLifecycleListener init
    信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: E:Program FilesJavajre7in;C:WindowsSunJavain;C:Windowssystem32;C:Windows;C:Program Files (x86)M1 Licensing;C:Program FilesBroadcomBroadcom 802.11 Network AdapterDriver;C:Program Files (x86)NVIDIA CorporationPhysXCommon;C:PROGRAM FILES (X86)INTELICLS CLIENT;C:PROGRAM FILESINTELICLS CLIENT;C:WindowsSYSTEM32;C:Windows;C:WindowsSYSTEM32WBEM;C:WindowsSYSTEM32WINDOWSPOWERSHELLV1.0;C:PROGRAM FILES (X86)INTELOPENCL SDK2.0BINX86;C:PROGRAM FILES (X86)INTELOPENCL SDK2.0BINX64;C:PROGRAM FILESINTELINTEL(R) MANAGEMENT ENGINE COMPONENTSDAL;C:PROGRAM FILESINTELINTEL(R) MANAGEMENT ENGINE COMPONENTSIPT;C:PROGRAM FILES (X86)INTELINTEL(R) MANAGEMENT ENGINE COMPONENTSDAL;C:PROGRAM FILES (X86)INTELINTEL(R) MANAGEMENT ENGINE COMPONENTSIPT;C:PROGRAM FILES (X86)LENOVOACCESS CONNECTIONS;C:Program FilesWIDCOMMBluetooth Software;C:Program FilesWIDCOMMBluetooth Softwaresyswow64;C:Program Files (x86)IntelOpenCL SDK3.0inx86;C:Program Files (x86)IntelOpenCL SDK3.0inx64;E:Ruby200in;E:Program FilesTortoiseSVNin;E:Program FilesMySQLMySQL Utilities 1.3.4;C:Program FilesMicrosoftWeb Platform Installer;C:Program Files (x86)Microsoft ASP.NETASP.NET Web Pagesv1.0;C:Program Files (x86)Windows Kits8.0Windows Performance Toolkit;C:Program FilesMicrosoft SQL Server110ToolsBinn;E:Program FilesJavajdk1.7.0_40in;C:Program Files (x86)Microsoft SQL Server100ToolsBinn;C:Program FilesMicrosoft SQL Server100ToolsBinn;C:Program FilesMicrosoft SQL Server100DTSBinn;F:instantclient;.;;.;;.
    三月 24, 2014 5:56:12 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin
    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:FilterTest' did not find a matching property.
    三月 24, 2014 5:56:13 下午 org.apache.coyote.AbstractProtocolHandler init
    信息: Initializing ProtocolHandler ["http-bio-8080"]
    三月 24, 2014 5:56:13 下午 org.apache.coyote.AbstractProtocolHandler init
    信息: Initializing ProtocolHandler ["ajp-bio-8009"]
    三月 24, 2014 5:56:13 下午 org.apache.catalina.startup.Catalina load
    信息: Initialization processed in 1031 ms
    三月 24, 2014 5:56:13 下午 org.apache.catalina.core.StandardService startInternal
    信息: Starting service Catalina
    三月 24, 2014 5:56:13 下午 org.apache.catalina.core.StandardEngine startInternal
    信息: Starting Servlet Engine: Apache Tomcat/7.0.8
    EncodeFilter init
    三月 24, 2014 5:56:13 下午 org.apache.catalina.startup.HostConfig deployDirectory
    信息: Deploying web application directory docs
    三月 24, 2014 5:56:13 下午 org.apache.catalina.startup.HostConfig deployDirectory
    信息: Deploying web application directory examples
    三月 24, 2014 5:56:13 下午 org.apache.catalina.core.ApplicationContext log
    信息: ContextListener: contextInitialized()
    三月 24, 2014 5:56:13 下午 org.apache.catalina.core.ApplicationContext log
    信息: SessionListener: contextInitialized()
    三月 24, 2014 5:56:13 下午 org.apache.catalina.startup.HostConfig deployDirectory
    信息: Deploying web application directory host-manager
    三月 24, 2014 5:56:13 下午 org.apache.catalina.startup.HostConfig deployDirectory
    信息: Deploying web application directory manager
    三月 24, 2014 5:56:14 下午 org.apache.catalina.startup.HostConfig deployDirectory
    信息: Deploying web application directory ROOT
    三月 24, 2014 5:56:14 下午 org.apache.coyote.AbstractProtocolHandler start
    信息: Starting ProtocolHandler ["http-bio-8080"]
    三月 24, 2014 5:56:14 下午 org.apache.coyote.AbstractProtocolHandler start
    信息: Starting ProtocolHandler ["ajp-bio-8009"]
    三月 24, 2014 5:56:14 下午 org.apache.catalina.startup.Catalina start
    信息: Server startup in 978 ms
    复制代码

    其中有filter,init方法的输出,下面创建一个index.html文件,内容如下:

    复制代码
     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Insert title here</title>
     6 </head>
     7 <body>
     8     <form action="http://localhost:8080/FilterTest/helloServlet" method="post">
     9         <input type="submit" value="Login">
    10     </form>
    11 </body>
    12 </html>
    复制代码

    点击index.html页面的按钮,

    此时Console输出内容:

    1 EncodeFilter doFilter

    每次请求都会有这样一条输出。

    关闭tomcat的时候,注意观察Console输出的内容:

    复制代码
    三月 24, 2014 6:08:33 下午 org.apache.catalina.core.StandardServer await
    信息: A valid shutdown command was received via the shutdown port. Stopping the Server instance.
    三月 24, 2014 6:08:33 下午 org.apache.coyote.AbstractProtocolHandler pause
    信息: Pausing ProtocolHandler ["http-bio-8080"]
    三月 24, 2014 6:08:34 下午 org.apache.coyote.AbstractProtocolHandler pause
    信息: Pausing ProtocolHandler ["ajp-bio-8009"]
    三月 24, 2014 6:08:35 下午 org.apache.catalina.core.StandardService stopInternal
    信息: Stopping service Catalina
    EncodeFilter destroy
    三月 24, 2014 6:08:36 下午 org.apache.catalina.core.ApplicationContext log
    信息: SessionListener: contextDestroyed()
    三月 24, 2014 6:08:36 下午 org.apache.catalina.core.ApplicationContext log
    信息: ContextListener: contextDestroyed()
    三月 24, 2014 6:08:37 下午 org.apache.coyote.AbstractProtocolHandler stop
    信息: Stopping ProtocolHandler ["http-bio-8080"]
    三月 24, 2014 6:08:37 下午 org.apache.coyote.AbstractProtocolHandler stop
    信息: Stopping ProtocolHandler ["ajp-bio-8009"]
    复制代码

    此时Fileter的Destroy方法被调用。Filter的生命周期结束。这篇文章中包含一些信息,如Server,Service,Container等,可能有些人跟我一样开始的时候对此很不了解,如果这样大家可以查一下Tomcat等web容器的工作原理,如果有什么地方我说的不清楚,或者有错误,那么请提醒我,谢谢。

    参考:http://www.journaldev.com/1933/java-servlet-filter-example-tutorial

  • 相关阅读:
    【常用配置】Spring框架web.xml通用配置
    3.从AbstractQueuedSynchronizer(AQS)说起(2)——共享模式的锁获取与释放
    2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放
    1.有关线程、并发的基本概念
    0.Java并发包系列开篇
    SpringMVC——DispatcherServlet的IoC容器(Web应用的IoC容器的子容器)创建过程
    关于String的问题
    Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)
    <<、>>、>>>移位操作
    System.arraycopy(src, srcPos, dest, destPos, length) 与 Arrays.copyOf(original, newLength)区别
  • 原文地址:https://www.cnblogs.com/wnlja/p/4346559.html
Copyright © 2011-2022 走看看