Servlet Filter 学习

##S: 个人认为Filter是为了能在request到达servlet之前做一些预处理工作或在离开当前servlet 时对response进行一些处理,这些就是Filter为什么需要Filter的出在,比如在下面的例子中,在web.xml里配置了/*的mapping,也就是说所有的servlet和jsp url都要经过这个filter,filter会将指定的encoding方式放到request中,这样再通过chain.doFilter传到下一个filter,如果没有下一个filter,那么它会到达servlet或jsp,这样servlet和jsp便可以使用新的encoding 的值了。

  其实Filter的原理实际是使用了职责链模式,当有多个Filter组成一个链时,你更容易发现,当一个Filter也就相当于每一个Handler处理完之后,它会通过chain.doFilter将请求传给下个filter也就是Handler去处理,这里的chain就是相当于下一个handler,可以看成传入的下一个handler的变量赋给了chain,然后通过chain去调用下一个处理器的处理请求的方法doFilter.

    *每个Filter类的doFilter方法就相当于处理请求的处理方法

    *chain就是代表那条filter链中的下一个handler参数。

---------------------------------------------------------------------------------------------------------------------------------

参考:http://www.blogjava.net/yangaiyou/archive/2007/08/29/140854.html

 

###2)web.xml 中的listener、 filter、servlet 加载顺序及其详解

 

 

在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰。

        首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关。即不会因为 filter 写在 listener 的前面而会先加载 filter。最终得出的结论是:listener -> filter -> servlet

        同时还存在着这样一种配置节:context-param,它用于向 ServletContext 提供键值对,即应用程序上下文信息。我们的 listener, filter 等在初始化时会用到这些上下文中的信息,那么 context-param 配置节是不是应该写在 listener 配置节前呢?实际上 context-param 配置节可写在任意位置,因此真正的加载顺序为:context-param -> listener -> filter -> servlet

        对于某类配置节而言,与它们出现的顺序是有关的。以 filter 为例,web.xml 中当然可以定义多个 filter,与 filter 相关的一个配置节是 filter-mapping,这里一定要注意,对于拥有相同 filter-name 的 filter 和 filter-mapping 配置节而言,filter-mapping 必须出现在 filter 之后,否则当解析到 filter-mapping 时,它所对应的 filter-name 还未定义。web 容器启动时初始化每个 filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多个 filter-mapping 时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调用 doFilter() 方法的。

        servlet 同 filter 类似 ,此处不再赘述。

       由此,可以看出,web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ,而同个类型之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
http://www.cnblogs.com/JesseV/archive/2009/11/17/1605015.html
 ----------Filter 例文1-----start-------

servlet filter

博客分类:

Java Filter过滤机制详解

以前以为Filter只是一个特殊点的Servlet,用进只需在web.xml中配置一下拦截路径就可以了,可经过这两天的深入学习,才知道以前对Filter类的了解和使用都太过浅薄了。

在网上看了很多篇相关的技术文章,现提取它们中的精髓(我认为能说明问题的东西)及我个人的一些学习经验作如下总结,希望能帮助大家更好地理解Filter的过滤机制。

要学习Filter,就必须先理解和掌握servlet的调用机制和流程。关于servlet,网上也有很多相关文章,大家若有不明白的可以到百度中搜一下,我这里为了突出重点就不多说了。好,下面进入正题。

一、什么是Filter

       
     Filter 技术是servlet 2.3 新增加的功能.servlet2.3是sun公司与2000年10月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原则.由于众多的参与者的共同努力,servlet2.3比以往功能都强大了许多,而且性能也有了大幅提高.

  它新增加的功能包括:

  1. 应用程序生命周期事件控制;

  2. 新的国际化;

  3. 澄清了类的装载规则;

  4. 新的错误及安全属性;

  5. 不赞成使用HttpUtils 类;

  6. 各种有用的方法;

  7. 阐明并扩展了几个servlet DTD;

  8. filter功能.

  其中最重要的就是filter功能.它使用户可以改变一个request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链).一个filter 包括:

  1. 在servlet被调用之前截获;

  2. 在servlet被调用之前检查servlet request;

  3. 根据需要修改request头和request数据;

  4. 根据需要修改response头和response数据;

  5. 在servlet被调用之后截获.

        你能够配置一个filter 到一个或多个servlet;单个servlet或servlet组能够被多个filter 使用.几个实用的filter 包括:用户辨认filter,日志filter,审核filter,加密filter,符号filter,能改变xml内容的XSLTfilter等.

       一个filter必须实现javax.servlet.Filter接口定义的三个方法: doFilter、init和destroy。(在三个方法在后面后有详细的介绍).

二、Filter体系结构

        2.1Filter工作原理(执行流程)      

       当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。

************************************************************************************************************************

           在这里,我要插几句——关于过滤链的问题:上面说了,当一个请求符合某个过滤器的过滤条件时该请求就会交给这个过滤器去处理。那么当两个过滤器同时过滤一个请求时谁先谁后呢?这就涉及到了过滤链FilterChain。

         所有的奥秘都在Filter的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。(注:这一点Filter和Servlet是不一样的,具体请参看我的另一篇文章:ServletFilter映射匹配原则之异同)执行的顺序就如下图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。

        
        这里还有一点想补充:大家有没有想过,上面说的“执行请求的资源”究竟是怎么执行的?对于“执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码”这些我可以理解,无非就是按顺序执行一句句的代码,但对于这个“执行请求的资源”我刚开始却是怎么也想不明白。直到我见到上面这张图片才恍然大悟(我说过了,这篇文章中的资料都是我从网上收集来的,当我看到上面的文字时是没有图片看的)。其实是这样的:

        通常我们所访问的资源是一个servlet或jsp页面,而jsp其实是一个被封装了的servlet(每个jsp执行前都会被转化为一个标准的servlet,这点若还有不明白的请自己到网上查一下吧),于是我们就可以统一地认为我们每次访问的都是一个Servlet,而每当我们访问一个servlet时,web容器都会调用该Servlet的service方法去处理请求。而在service方法又会根据请求方式的不同(Get/Post)去调用相应的doGet()或doPost()方法,实际处理请求的就是这个doGet或doPost方法。写过servlet的朋友都应该知道,我们在doGet(或doPost)方法中是通过response.getWriter()得到客户端的输出流对象,然后用此对象对客户进行响应。

       到这里我们就应该理解了过滤器的执行流程了:执行第一个过滤器的chain.doFilter()之前的代码——>第二个过滤器的chain.doFilter()之前的代码——>……——>第n个过滤器的chain.doFilter()之前的代码——>所请求servlet的service()方法中的代码——>所请求servlet的doGet()或doPost()方法中的代码——>第n个过滤器的chain.doFilter()之后的代码——>……——>第二个过滤器的chain.doFilter()之后的代码——>第一个过滤器的chain.doFilter()之后的代码。

       以上是我的理解,若有不对之处,还有大家不吝指教啊,大家一起学习!!

************************************************************************************************************************

2.2 Servlet过滤器API
          Servlet过滤器API包含了3个接口,它们都在javax.servlet包中,分别是Filter接口、FilterChain接口和FilterConfig接口。
       2.2.1     public Interface Filter
                    所有的过滤器都必须实现Filter接口。该接口定义了init,doFilter0,destory()三个方法:
    (1) public void init (FilterConfig filterConfig) throws   ServletException.
          当开始使用servlet过滤器服务时,Web容器调用此方法一次,为服务准备过滤器;然后在需要使用过滤器的时候调用doFilter(),传送给此方法的FilterConfig对象,包含servlet过滤器的初始化参数。
    (2)public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
                                              throws java.io.IOException,ServletException.

         每个过滤器都接受当前的请求和响应,且FilterChain过滤器链中的过滤器(应该都是符合条件的)都会被执行。doFilter方法中,过滤器可以对请求和响应做它想做的一切,通过调用他们的方法收集数据,或者给对象添加新的行为。过滤器通过传送至此方法的FilterChain参数,调用chain.doFilterO将控制权传送给下一个过滤器。当这个调用返回后,过滤器可以在它的 Filter方法的最后对响应做些其他的工作。如果过滤器想要终止请求的处理或得到对响应的完全控制,则可以不调用下一个过滤器,而将其重定向至其它一些页面。当链中的最后一个过滤器调用chain.doFilterO方法时,将运行最初请求的Servlet。
     (3)public void destroy()
        一旦doFilterO方法里的所有线程退出或已超时,容器调用
此方法。服务器调用destoryO以指出过滤器已结束服务,用于释
放过滤器占用的资源。


2.2.2 public interface FilterChain
      public void doFilter(ServletRequest request,ServletResponse response)
    thlows java.io.IOException,ServletException
      此方法是由Servlet容器提供给开发者的,用于对资源请求过滤链的依次调用,通过FilterChain调用过滤链中的下一个过滤   器,如果是最后一个过滤器,则下一个就调用目标资源。


   2.2.3 public interface FilterConfig
      FilterConfig接口检索过滤器名、初始化参数以及活动的Servlet上下文。该接口提供了以下4个方法:
     (1)public java.1ang.String getFilterName0
           返回web.xml部署文件中定义的该过滤器的名称。
     (2)public ServletContext getServletContextO
          返回调用者所处的servlet上下文。
     (3)public java.1ang.String getlnitParameter(java.1ang.String name)
          返回过滤器初始化参数值的字符串形式,当参数不存在时,返回nul1.name是初始化参数名。
     (4)public java.util.Enumeration getlnitParameterNames()
          以Enumeration形式返回过滤器所有初始化参数值,如果没有初始化参数,返回为空。

   2.3、过滤器相关接口工作流程
   从编程的角度看,过滤器类将实现Filter接口,然后使用这个过滤器类中的FilterChain和FilterConfig接口。该过滤器类的
— 个引用将传递给FilterChain对象,以允许过滤器把控制权传递给链中的下一个资源。FilterConfig对象将由容器提供给过滤
器,以允许访问该过滤器的初始化数据。详细流程如下图所示:

2.4、过滤器配置
    过滤器通过Web应用程序中的配置描述符web.xml文件中的明,包括部分:过滤器定义,由<filter>
元素表示,主要包括<filter-name>和<f'flter-class>两个必须的子元素和<icon>、<init-param>,<display-name>,<description>这4个可选的子元素。<filter-name>子元素定义了—个过滤器的名字,<filter-class>指定了由容器载入的实际类,<init-param>子元素为过滤器提供初始化参数。

        <filter-mapping> 主要由<filter-name>,<servlet-name>和<url-pattem>子元素组成。<servlet-name>将过滤器映射到一个或多个Servlet上,<url-pattem>将过滤器映射到—个或多个任意特征的URL的JSP页面。

三、应用实例
          从上面分析可知,实现Servlet过滤器,需要两步:第一步开发过滤器,设计—个实现Fiker接口的类;第二步通过web.xml配置过滤器,实现过滤器和Servlet、JSP页面之间的映射。以下设计一个简单的IP地址过滤器,根据用户的IP地址进行对网站的访问控制。
(1)过滤器的设计ipfilter.java
package ipf;
imp0rt java.io.IOException;
imp0rt javax.servlet.*;
public class ipfilter implements Filter//实现Filter接口
{protected FilterConfig config;
protected String rejectedlP;
public void init(FilterConfig filterConfig)throws
ServletException
{this.config=filterConfig;//从Web)lE务器获取过滤器配置对象
rejectedlP=config.getlnitParameter( RejectedlP”):
,,从配置中取得过滤lP
if(rejectedlP=:nul1)‘rejectedlP= )
)
public void doFilter(ServletRequest request,
ServletResponse response.FilterChain chain)throws
IOException,ServletException
{RequestDispatcher dispatcher=request.getRequestDispatcher("");
String remotelP=request.getRemoteAddrO;//获取客户请求lP
int i=remotelP.1astlndexOf(".");
int r=rejectedlP.1astlndexOf(”.”):
String relPscope=rejectedlP.substring(0,r);//过滤lP段
if(relPscope.equals(remotelP.substring(O.i)))
{      dispatcher.forward(request,response);//重定向到rejectedError.jsp页面
        retum;//阻塞,直接返Web回客户端
}
else{chain.doFilter(request,response);//调用过滤链上的下一个过滤器
}
}
public void destroy()
       //过滤器功能完成后,由Web服务器调用执行,回收过滤器资源
注意:chain.doFilterO语句以前的代码用于对客户请求的处理;以后的代码用于对响应进行处理。
(2)配置过滤器
    在应用程序Web—INF目录下的web.xml描述符文件中添加以下代码:

<filter>
<filter-name>ipfIter</filter-name>//过滤器名称
<filter-class>ipf.ipfiIter</filter-class>//实现过滤器的类
<init—param>
<param—name>RejectedlP</param-name>//过滤器初始化参数名RejectedlP
<param-value>192.168.12.*/param-value>
</init—pamm>
</filter>
<filter-mapping>//过滤器映射(规律规则)
<filter-name>ipfiIter</filter-name>
<url—pattem>/*</ud-pattem>
//映射到Web应用根目录下的所有JSP文件
</filter-mapping>
通过以上设计与配置,就禁止了IP地址处在192.168.12网段的用户对网站的访问。

四、结束语
Servlet过滤器功能强大,应用广泛,除支持Servlet和JSP页面的基本功能,比如13志记录、性能、安全、会话处理、XSLT转换等外,在J2EE应用程序中使用Java Servlet过滤器转换其输出,以便兼容任何类型客户端也表现出了很好的前景。Servlet过滤器能够侦测到来自使用WAP协议(无线应用协议)的移动客户端的呼叫,并且将答复内容转换成WML(无线标记语言)格式。Servlet过滤器也能检测到来自iMode无线客户的呼叫,并将其转变成cHTML(紧凑HTML)格式等等。因而,深刻理解Servlet过滤器的工作机制,熟练掌握编程技术,在实际的开发过程中,可以不断地发现新的用途,增强组件的可重用性,提高Web应用程序的可维护性。

 

 

 

2009-06-09

Servlet与Filter

1Servlet是使用Java Servlet应用程序设计接口及相关类和方法的Java程序。它通过创建一个框架来扩展服务器的能力,以提供在Web上进行请求和响应服务,充当一个桥梁的角色来联系客户机与应用程序,负责把客户机发出的请求封装成程序人员编写的应用程序中需要的对象。当客户机发送请求至服务器时,服务器可以将请求信息发送给 Servlet,并让 Servlet 建立起服务器返回给客户机的响应。当启动 Web 服务器或客户机第一次请求服务时,可以自动装入 Servlet。装入后, Servlet 继续运行直到其它客户机发出请求。

2
Servlet的生命周期始于将它装入Web服务器的内存时,并在终止或重新装入Servlet时结束。

  (1) 初始化

  在下列时刻装入 Servlet

 如果已配置自动装入选项,则在启动服务器时自动装入

 在服务器启动后,客户机首次向 Servlet 发出请求时

 重新装入 Servlet 时装入 Servlet 后,服务器创建一个 Servlet 实例并且调用 Servlet init() 方法。在初始化阶段,Servlet 初始化参数被传递给 Servlet 配置对象。

  (2) 请求处理

  对于到达服务器的客户机请求,服务器创建特定于请求的一个请求对象和一个响应对象。服务器调用 Servlet service() 方法,该方法用于传递请求响应对象。service() 方法从请求对象获得请求信息、处理该请求并用响应对象的方法以将响应传回客户机。service() 方法可以调用其它方法来处理请求,例如 doGet()doPost() 或其它的方法。

  (3) 终止

  当服务器不再需要 Servlet, 或重新装入 Servlet 的新实例时,服务器会调用 Servlet destroy() 方法。


3
servlet的配置

Java代码

  1. <servlet>   
  2.     <servlet-name>advExtract</servlet-name>   
  3.     <servlet-class>   
  4.         com.anne.servlet.AdvExtractServlet   
  5.     </servlet-class>   
  6.     <init-param>   
  7.         <param-name>encoding</param-name>   
  8.         <param-value>UTF-8</param-value>   
  9.     </init-param>   
  10.     <load-on-startup>1</load-on-startup>   
  11. </servlet>   
  12. <servlet-mapping>   
  13.     <servlet-name>advExtract</servlet-name>   
  14.     <url-pattern>/ad/</url-pattern>   
  15. </servlet-mapping>  
  <servlet>
   <servlet-name>advExtract</servlet-name>
   <servlet-class>
     com.anne.servlet.AdvExtractServlet
   </servlet-class>
   <init-param>
     <param-name>encoding</param-name>
     <param-value>UTF-8</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
   <servlet-name>advExtract</servlet-name>
   <url-pattern>/ad/</url-pattern>
  </servlet-mapping>



Servlet的配置一定要有<servlet></servlet><servlet-mapping></servlet-mapping>
<init-param>
的作用:

配置了初始化servlet需要用到的参数。

Java代码

  1. public class AdvExtractServlet extends HttpServlet{   
  2.     private String encoding;           
  3.     @Override  
  4.     public void init(ServletConfig config) throws ServletException {   
  5.         super.init(config);   
  6.         encoding = config.getInitParameter("encoding");   
  7.         ……   
  8.     }   
  9. }  
public class AdvExtractServlet extends HttpServlet{
  private String encoding;   
  @Override
  public void init(ServletConfig config) throws ServletException {
   super.init(config);
   encoding = config.getInitParameter("encoding");
   ……
  }
}


如上面<init-param>中配置了encodingUTF-8,那么在override HttpServlet类的init()方法的时候,就可以从config中取出”encoding”的值”UTF-8”

4
Filter

  Filter
servlet是密不可分的。Tomcat在接收到一个来自客户端(如浏览器)的请求之后,在这个请求被传递给servlet之前,需要经过层层Filter的过滤。它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response


一个filter必须实现javax.servlet.Filter接口并定义三个方法
:
1.void setFilterConfig(FilterConfig config) //
设置filter 的配置对象

2. FilterConfig getFilterConfig() //
返回filter的配置对象
;
3. void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) //
执行filter 的工作


Filter
servlet是一个层层包裹的关系,如下图:
 



 

对于每个request,将会先进入Filter1doFilter()方法,在这个方法中会调用chain.doFilter()方法把控制权交给Filter2,然后在Filter2doFilter()方法中会调用servletservici()方法,进入servlet,在离开servlet一层之后,依次退回到Filter2Filter1,进行doFilter()中的后续处理,这里可以对从servlet返回来的response进行处理。

因此filter的实质就是拦截器(interceptor),它与Spring AOP中的包围通知(MethodInterceptor)类似,层层的包围住servlet


常见的filter的应用有:权限控制(如Acegi的实现),记录日志,转换编码格式,加密等。

---------Filter 例文2-----end-------

 

Filter的使用实例

分类: J2EE 1026人阅读 评论(0) 收藏 举报

 

     JSP技术构建在Servlet技术之上,所以Servlet和JSP的技术本质是一样的,JSP能做到的,Servlet都能做到,但是它们却各有所长。Servlet比较适合作为控制类组件,比如视图控制器等。另外,Servlet还可以作为过滤器、监听器等。Servlet不仅可以动态生成HTML内容,还可以动态生成图形。总而言之,Servlet在项目中作为控制类的组件,并且处理一些后台业务,JSP则作为显示组件。

    在本节,我们将介绍Servlet常用的使用方法之一:作为过滤器。在Servlet作为过滤器使用时,它可以对客户的请求进行过滤处理,当它处理完成后,它会交给下一个过滤器处理,就这样,客户的请求在过滤链里一个个处理,直到请求发送到目标。举个例子,某个网站里有提交"修改的注册信息"的网页,当用户填写完成修改信息并提交后,服务端在进行真正的处理时需要做两个处理:客户端的会话是否有效;对提交的数据进行统一的编码,比如GB2312。这两个处理可以在由两个过滤器组成的过滤链里进行处理。当过滤器处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功(比如客户端的会话无效),它将把视图派发到指定的错误页面。可以看出,过滤器就像一扇门,客户端要和服务端的某个目标交互,必须通过这扇门。

    下面我们来看一个具体的例子,这个例子将介绍怎么开发过滤器,并且介绍怎么在web.xml文件里配置过滤器。这个例子里有两个JSP页面,前一个页面用户输入一些信息然后提交,后一个页面显示用户提交的信息。在提交信息后,要经过两个过滤器的处理,一个检查用户是否登录,一个把用户的提交信息用GB2312进行重新编码。

    开发一个Filter,这个Filter需要实现Filter接口,Filter接口定义了以下的方法:

<CCID_NOBR>
<CCID_CODE>destroy() //由Web容器调用,销毁此Filter
init(FilterConfig filterConfig) ///由Web容器调用,初始化此Filter
doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain)//具体过滤处理代码


    下面我们来看对提交信息用GB2312进行重新编码的Filter,见示例14-7、示例14-8。
    【程序源代码】

<CCID_NOBR>
<CCID_CODE>1	// ==================== Program Discription =====================
2	// 程序名称:示例14-7 : EncodingFilter .java
3	// 程序目的:学习使用编码过滤器
4	// ==============================================================
5	import javax.servlet.FilterChain;
6	import javax.servlet.ServletRequest;
7	import javax.servlet.ServletResponse;
8	import java.io.IOException;
9	import javax.servlet.Filter;
10	import javax.servlet.http.HttpServletRequest;
11	import javax.servlet.http.HttpServletResponse;
12	import javax.servlet.ServletException;
13	import javax.servlet.FilterConfig;
14	
15	public class EncodingFilter implements Filter
16	{
17	    
18	    private String targetEncoding = "gb2312";
19	    protected FilterConfig filterConfig;
20	    
 
21	    public void init(FilterConfig config) throws ServletException {
22	        this.filterConfig = config;
23	        this.targetEncoding = config.getInitParameter("encoding");
24	    }
25	    
26	   
27	     public  void doFilter(ServletRequest srequest, 
ServletResponse  sresponse,FilterChain chain)
28	        throws IOException, ServletException {
29	       
30	        HttpServletRequest request = (HttpServletRequest)srequest;
31	        request.setCharacterEncoding(targetEncoding);//把请求用指定的方式编码
32	        // 把处理发送到下一个过滤器
33	       chain.doFilter(srequest,sresponse);  
34	    }
35	    
36	    public void destroy()
37		{
38			this.filterConfig=null;
39		}
40	
41		public void setFilterConfig(final FilterConfig filterConfig)
42		{
43			this.filterConfig=filterConfig;
44		}
45	}


    【程序源代码】

<CCID_NOBR>
<CCID_CODE>1	// ==================== Program Discription =====================
2	// 程序名称:示例14-8 : LoginFilter.java
3	// 程序目的:学习使用登录过滤器
4	// ==============================================================
5	import javax.servlet.FilterChain;
6	import javax.servlet.ServletRequest;
7	import javax.servlet.ServletResponse;
8	import java.io.IOException;
9	import javax.servlet.Filter;
10	import javax.servlet.http.HttpServletRequest;
11	import javax.servlet.http.HttpServletResponse;
12	import javax.servlet.ServletException;
13	import javax.servlet.FilterConfig;
14
15	public class LoginFilter implements Filter
16	{
17		String LOGIN_PAGE="init.jsp";
18		protected FilterConfig filterConfig;
 
19		public void doFilter(final ServletRequest req,final ServletResponse 
res,FilterChain chain)throws IOException,ServletException
20		{
21			 HttpServletRequest hreq = (HttpServletRequest)req;
22	         HttpServletResponse hres = (HttpServletResponse)res;	
23	         String isLog=(String)hreq.getSession().getAttribute("isLog");	 
24 if((isLog!=null)&&((isLog.equals("true"))||(isLog=="true")))//检查是否登录
25			 {
26			 	chain.doFilter(req,res);
27			 	return ;
28			 }
29			 else
30			 	hres.sendRedirect(LOGIN_PAGE);//如果没有登录,把视图派发到登录页面
31		}
32		
33		public void destroy()
34		{
35			this.filterConfig=null;
36		}
37		public void init(FilterConfig config)
38		{
39			this.filterConfig=config;
40		}
41		public void setFilterConfig(final FilterConfig filterConfig)
42		{
43			this.filterConfig=filterConfig;
44		}	
45	}


    【程序注解】
    正如前面所说,EncodingFilter的目的是把客户端的请求用指定的方式编码,具体的处理在request.setCharacterEncoding(targetEncoding)完成了。LoginFilter判断用户在进入目标之前是否登录,if((isLog!=null)&&((isLog.equals("true"))||(isLog=="true")))将检查用户是否登录,如果已登录,那么把视图让过滤链继续处理,如果没有登录,把视图派发到登录页面,过滤链处理结束。
下面我们来看怎么在web.xml里配置这两个过滤器,代码如下所示:
    【程序源代码】

<CCID_NOBR>
<CCID_CODE><web-app>
  <filter>
     <filter-name>encoding</filter-name> 
           <filter-class>EncodingFilter</filter-class> 
           <init-param>
    	        <param-name>encoding</param-name>
    	        <param-value>gb2312</param-value>
 
    	</init-param>
    </filter>    
    <filter>
    	<filter-name>auth</filter-name>
    	<filter-class>LoginFilter</filter-class>
    </filter>
    
    <filter-mapping> 
       <filter-name>encoding</filter-name> 
       <url-pattern>/*</url-pattern>  
     </filter-mapping>  
    <filter-mapping>
    		<filter-name>auth</filter-name>
   		<url-pattern>/target.jsp</url-pattern>
   	</filter-mapping>   	
</web-app>


    【程序注解】
    可以看出,配置Filter时,首先指定Filter的名字和Filter的实现类,如果有必要,还要配置Filter的初始参数;然后为Filter做映射,这个映射指定了需要过滤的目标(JSP、Servlet)。在上面的例子中,指定了EncodingFilter 为所有的JSP和Servlet做过滤,LoginFilter为target.jsp做过滤。这样,当客户请求target.jsp时,首先要经过EncodingFilter的处理,然后经过LoginFilter的处理,最后才把请求传递给target.jsp。

    【运行程序】
    把程序部署到Web服务器里(比如Tomcat),然后启动Web服务器,在浏览器里输入以下URL(根据具体请求改变URL):http://127.0.0.1:8080/ch14/target.jsp

    那么Filter将会把视图派发到:http://127.0.0.1:8080/ch14/init.jsp

    在init.jsp里,我们使用:

<CCID_NOBR>
<CCID_CODE><% session.setAttribute("isLog","true");%>


    来设置用户已经登录(这里是简化的,在实际项目中,可能要经过验证处理)。在init.jsp里,可以提交一些中文的信息。由于提交的信息被EncodingFilter使用GB2312统一编码了,故在target.jsp里能够正确显示中文。您可以做一个试验,把

<CCID_NOBR>
<CCID_CODE><filter-mapping> 
       <filter-name>encoding</filter-name> 
       <url-pattern>/*</url-pattern>  
</filter-mapping>


改为

<CCID_NOBR>
<CCID_CODE><filter-mapping> 
       <filter-name>encoding</filter-name> 
       <url-pattern>/nothing</url-pattern>  
</filter-mapping>


    然后重新启动Web服务器。那么在target.jsp里,中文将不能正确显示。(T111)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值