JAVA开发(7) - filter

filter的意思简单的说就是过滤器,它的作用就是当用户请求一个url之前,可以预先做一些处理,当请求完url返回给用户之前还可以做一些处理(所以filter的功能十分的强大,如果想做的话可以强大到让用户,不能访问请求的url的程度。。。)<?XML:NAMESPACE PREFIX = O ?>

 

接口javax.servlet.Filter

 

   void init(FilterConfig filterConfig)

   可以在此方法中完成Filter需要初始化的内容,在一个filter提供服务之前肯定会先调用此方法

 

       void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

当用户访问的url或者servlet被配置了使用此filter时,servlet/jsp容器会调用此方法,每次访问调用一次。chain参数为一个FilterChain接口的对象,可以简单的理解成chain包含了访问一个url上所有的需要调用的方法。

 

       void destroy()

当不需要一个filter再提供服务时调用,容器会调用此方法

 

filter的工作模式:

 

 

可以看到假如用户访问的一个url有两个filter的时候。

servlet容器会先调用最外层的filter(Filter1)doFilter()方法,然后在由Filter1中调用的chain.doFilter方法将控制权返回给容器,接着容器调用第二层filter(Filter2)doFilter方法,然后在由Filter2中调用的chain.doFilter方法将控制权返回给容器,这个时候容器才能去访问真正的需要请求的servletjsp,但servletjsp执行完毕以后,会运行Filter2doFilter方法调用的chain.doFilter方法后剩余的代码片断,之后再运行Filter1doFilter方法调用的chain.doFilter方法后剩余的代码片断。

 

Filter对应的请求方式有4种:requestforwardincludeerror

 

request:当用户直接请求一个网页时才会通过此filter,当用户通过RequestDispatcher(会再后面详细介绍该类的方法)forward不会通过该filter

forward: 当用户通过RequestDispatcherforward方法访问对应的url时才会通过该filter

include:当用户通过RequestDispatcherinclude方法访问对应的url时才会通过该filter

error:当用户的请求通过错误处理机制的时候才会通过该filter(目前不准备详细论述)

 

一个filter可以对应几种请求方式,但是如果配置时不写请求方式的话,默认方式为request

 

下面先举一个例子看下filter工作的过程:

 

FilterFirst

 

package  squall.servlet.filter;

 

import  java.io.IOException;

 

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  FilterFirst  implements  Filter

... {

 

       
public void destroy()

       
...{

 

       }


 

       
public void doFilter(ServletRequest request, ServletResponse response,

                     FilterChain chain) 
throws IOException, ServletException

       
...{

              System.out.println(
"Begin First Filter!");

              chain.doFilter(request, response);

              System.out.println(
"After First Filter!");

       }


 

       
public void init(FilterConfig config) throws ServletException

       
...{

 

       }


 

}


 

 

FilterSecond

 

package  squall.servlet.filter;

 

import  java.io.IOException;

 

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  FilterSecond  implements  Filter

... {

 

       
public void destroy()

       
...{

 

       }


 

       
public void doFilter(ServletRequest request, ServletResponse response,

                     FilterChain chain) 
throws IOException, ServletException

       
...{

              System.out.println(
"Begin Second Filter!");

              chain.doFilter(request, response);

              System.out.println(
"After Second Filter!");

       }


 

       
public void init(FilterConfig config) throws ServletException

       
...{

              

       }


 

}


 

 

部署时修改web.xml如下:

在第一个<servlet>标签前添加:

       

   < filter >

        
< filter-name > FilterFirst </ filter-name >

        
< filter-class > squall.servlet.filter.FilterFirst </ filter-class >

    
</ filter >

    
< filter >

        
< filter-name > FilterSecond </ filter-name >

        
< filter-class > squall.servlet.filter.FilterSecond </ filter-class >

    
</ filter >

    

    
< filter-mapping >

        
< filter-name > FilterFirst </ filter-name >

              
< url-pattern > /HelloServlet </ url-pattern >

    
</ filter-mapping >

    
< filter-mapping >

        
< filter-name > FilterSecond </ filter-name >

              
< url-pattern > /HelloServlet </ url-pattern >

</ filter-mapping >

 

filter标签放置在一起,将filter-mapping标签放在再一起,顺序根据filter-name一致。这里的filter-mapping的顺序即为:假如我们访问的一个url有两个filter时,filter的先后顺序,web.xmlfilter-mapping在前面的filter先被执行。

 

部署完毕之后我们访问:http://127.0.0.1:8080/train/HelloServlet

可以看到tomcat管理控制台输出如下:

Begin First Filter

Begin Second Filter

After Second Filter

After First Filter

 

上面的例子可以看出filter工作的过程和我们上面的图片一致。

 

下面我们来举一个比较贴近实际的例子看一下filter的方便之处。

下面的例子用于常见的解决中文乱码的问题,我们为了防止中文乱码经常需要调用

HttpServletRequestHttpServletResponsesetCharacterEncoding方法,底下的这个filter的例子实现了,采用filter来解决这个问题。

Filterparam.html

 

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >

< html  xmlns ="http://www.w3.org/1999/xhtml" >

< head >

< META  http-equiv ="Content-Type"  content ="text/html; charset=GBK"   />  

< script  type ="text/javascript" > ...

       

       

function changeaction()

...{

       
var a = document.getElementsByName("filter");

       
for(i = 0; i < a.length; i++)

       
...{

              
if(a[i].checked==true)

              
...{

                     fm.action
=a[i].value;

                     
break;

              }


       }


}


</ script >

 

        
< title > filterparameter.html </ title >

</ head >

 

 

 

< body  bgcolor ="#FDF5E6" >

 

< h2 > Filter中文乱码示范 </ h2 >

 

< form  name  ="fm"  method ="post"  action ="FilterShowParameter/No" >

  

  
< p > 姓名: < input  type ="text"  name ="username"  size ="15"   />   </ p >

  

  
< p > 使用filter:

  
< input  name ="filter"  value ="FilterShowParameter/No"  type ="radio"  onclick ="changeaction()"  checked  />

       不使用

  
< input  name ="filter"  value ="FilterShowParameter/Yes"  type ="radio"  onclick ="changeaction()"   />

       使用

  
</ p >

  
< p >

  
< input  value ="确认"  type ="submit"   />

  
< input  value ="清除"  type ="reset"   />

  
</ p >

</ form >

 

 

</ body >

</ html >

 

直接放在train目录下

 

FilterShow

 

 

package  squall.servlet.basic;

 

import  java.io.IOException;

import  java.io.PrintWriter;

 

import  javax.servlet.ServletException;

import  javax.servlet.http.HttpServlet;

import  javax.servlet.http.HttpServletRequest;

import  javax.servlet.http.HttpServletResponse;

 

public   class  FilterShow  extends  HttpServlet

... {

       
protected void doGet(HttpServletRequest req, HttpServletResponse resp)

                     
throws ServletException, IOException

       
...{

              showParam( req,  resp);

       }


 

       
protected void doPost(HttpServletRequest req, HttpServletResponse resp)

                     
throws ServletException, IOException

       
...{

              showParam( req,  resp);

       }


       

       
private void showParam(HttpServletRequest req, HttpServletResponse resp) throws IOException

       
...{

              resp.setContentType(
"text/html");

              PrintWriter out 
= resp.getWriter();

              String docType 
= "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> ";

 

              String name 
= req.getParameter("username");

              

              out.println(docType 
+ "<HTML> " + "<HEAD><TITLE> showparam" 

                            
+ "</TITLE></HEAD> " + "<BODY BGCOLOR="#FDF5E6"> "

                            
+"     姓名:" + name + "   </br>"

                            );

 

          out.println(
"</body></html>");

       }


}


 

部署时将FilterShow mapping/FilterShowParameter/*

 

EncodingFilter

 

package  squall.servlet.filter;

 

import  java.io.IOException;

 

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  EncodingFilter  implements  Filter

... {

 

       
public void init(FilterConfig config) throws ServletException

       
...{

              String str 
= config.getInitParameter("encoding");

              
if (str != null && !"".equals(str))

                     encoding 
= str;

       }


 

       
public void doFilter(ServletRequest request, ServletResponse response,

                     FilterChain chain) 
throws IOException, ServletException

       
...{

              System.out.println(
"encoding is " + encoding);

              
if(encoding != null)

              
...{

                     request.setCharacterEncoding(encoding);

                     response.setCharacterEncoding(encoding);

              }


              chain.doFilter(request, response);

       }


 

       
public void destroy()

       
...{

 

       }


 

       
private String encoding = null;

 

}


 

 

EncodingFilter的功能就是将requestresponse setCharacterEncoding为预先定义好的encodinggetInitParameter 将在以后介绍。

 

EncodingFilter部署方式:

web.xml最后一个</filter>下添加

 

 

 

< filter >

        
< filter-name > EncodingFilter </ filter-name >

        
< filter-class > squall.servlet.filter.EncodingFilter </ filter-class >

        
< init-param >

               
< param-name > encoding </ param-name >

               
< param-value > GBK </ param-value >

        
</ init-param >

</ filter >

 

然后在最后一个</filter-mapping>下添加:

 

 

< filter-mapping >

        
< filter-name > EncodingFilter </ filter-name >

              
< url-pattern > /FilterShowParameter/Yes </ url-pattern >

              
< dispatcher > REQUEST </ dispatcher >

              
< dispatcher > FORWARD </ dispatcher >

    
</ filter-mapping >

 

部署完毕后访问http://127.0.0.1:8080/train/filterparam.html

输入姓名为中文以后,如果使用filter 选择为不使用则会看到乱码

选择使用filter则会看到正确的中文。

 

上面的例子是对REQUESTFORWARD使用filter

关于filter-mappinginclude方式做一个简单的说明,如下:

 

 

< filter-mapping >

        
< filter-name > FilterName </ filter-name >

              
< servlet-name > HelloServlet </ servlet-name >

              
< dispatcher > INCLUDE </ dispatcher >

 
</ filter-mapping >

 

include方式时必须将<url-pattern>修改为<servlet-name>

上面的filter-mapping的含义为:

HelloServlet这个servlet里调用RequestDispatcherinclude时,才会通过此filter

 

filter的功能远远不只上面举的例子,filter还可以对servletjsp输出至客户端的内容进行修改,还可以用来判断是否满足一些条件,假如不满足条件就不让访问者访问相应的条件,这里就不做一一的介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值