JSP的过滤器

来源:互联网 发布:复旦大数据学院金融 编辑:程序博客网 时间:2024/05/23 11:56

Servlet过滤器: 
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术可以对web服务器管理的所有web资源:Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。 
ServletAPI提供了一个Filter接口,实现这个接口的Servlet就是一个过虑器。过虑器在WEB应用访问流程中如下: 
由图可见,只要我们编写了过滤器,可以对一切访问WEB应用的连接进行过滤。比如,用户访问权限、统一WEB编码… 
Filter是如何实现拦截的? 
实现了Filter接口的Servlet是过滤器,因为Filter接口有一个doFilter(ServletRequest request, ServletResponse response, FilterChain chain)方法,只要用户访问我们在web.xml中配置的映射目录,服务器便会调用过滤器的doFilter方法。我们在这里实现过虑功能代码,当我们调用chain.doFilter(request, response);方法时,将请求反给服务器服务器再去调用相当的Servlet。如果我们不调用此方法,说明拒绝了用户的请求。 
Filter开发入门: 
在WEB应用中添加一个过滤器,有两步工作需要完成: 
1.编写实现了Filter接口的Servlet——过滤器。 
2.在web.xml中配置过滤器: 
(1). <filter>标签添加器 
(2). <filter-mapping>注册过滤器的映射目录(过滤目录),与注册Servlet一样。 
在实际WEB应用中,我们可能需要编写多个过虑器,比如:1.统一WEB编码的过滤器(过虑所有访问)2.用户访问权限管理。这样,用户的访问需要选经过过滤器1过滤然后再经过过滤器2过滤。doFilter中有一个FilterChain参数,这个参数是服务器根据web.xml中配置的过滤器,按照先后顺序生成的过滤器链。当我们在doFilter方法中调用chain.doFilter(request, response);方法时,服务器会查找过滤链中是否还有过滤器,如果有继续调用下一个过滤器,如果没有将调用相应的Servlet处理用户请求。 
Filter接口的其他细节: 
1.Filter的Init(FilterConfig filterConfig)方法: 
与Servlet的Init方法一样,在创建时被调用,之后被保存在内存中直至服务器重启或关闭时Filter实例才会被销毁。与Servlet不同之处在于,服务器启动时就会实例化所有Filter,而Servlet中有当用户第一次访问它时才会被实例化。我们通过在web.xml使用<init-param>对Filter配置的初始化参数,可以通过FilterConfig来获得。 
FilterConfig的方法有: 
String getFilterName():得到filter的名称。 
String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null. 
Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。 
public ServletContext getServletContext():返回Servlet上下文对象的引用。 
2.Filter的destroy()方法: 
当服务器重启或关闭时,在销毁Filter之前调用此方法。 
编写配置Filter练习程序: 
1. 编写一个用于统一WEB字符编码的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; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
public class Encoding implements Filter { 
public void destroy() { 
// TODO Auto-generated method stub 

public void doFilter(ServletRequest arg0, ServletResponse arg1, 
FilterChain arg2) throws IOException, ServletException { 
//参数转换,因为我们已经它肯定是Http协议的请求。 
HttpServletRequest request = (HttpServletRequest)arg0; 
HttpServletResponse response = (HttpServletResponse)arg1; 
//设置request和response使用的编码均为UTF-8。 
request.setCharacterEncoding("UTF-8"); 
response.setCharacterEncoding("UTF-8"); 
response.setContentType("text/html;charset=UTF-8"); 
//设置完成后,交回给服务器。 
arg2.doFilter(arg0, arg1); 

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



2. 配置web.xml文件,添加下面部分: 

<filter> 
<filter-name>encoding</filter-name> 
<filter-class>cn.itcast.cc.filter.Encoding</filter-class> 
</filter> 
<filter-mapping> 
<filter-name>encoding</filter-name> 
<url-pattern>/*</url-pattern> 
</filter-mapping> 


3. 上面是Filter的简单使用方式,后面会讲到高级应用。 
Filter高级开发: 
//参数转换,因为我们已经它肯定是Http协议的请求。 
HttpServletRequest request = (HttpServletRequest)arg0; 
HttpServletResponse response = (HttpServletResponse)arg1; 
上面的两片段代码,是因为我们已经知道了request和response是服务器给我们封装好了的两个Http请求对象。我们对它进行了功能上的扩充。如果我们不知道request和response是谁创建的具体内容是什么,我们应该如何对它们的功能进行扩充?我们有两种方式可以扩充: 
1. 编写一个子类,覆盖需要覆盖的方法。 
2. 使用Decorator设计模式,来扩充我们想要的功能。 
Decorator设计模式: 
我们有时无法使用方法1,因为我们不知道一个对象的具休类,比如它是一个接口对象,实现类是谁?。所以我们最好使用方法2,之前我们有接触过工厂设计模式和单例设计模式,Java真是高级应用的完美体现。什么是Decorator设计模式?中文名称是“装饰”模式,下面我们使用此模式为request做一下功能上的扩充: 
1.我们实现继承request接口类型ServletRequest。哦天哪,ServletRequest有太多的方法,难道我们要实现每一个方法?Servlet设计者们想到了这一点,并给我们提供了一个包装类——HttpServletRequestWrapper。我们就使用它做为父类吧! 
2.在我们自定义类内部添加一个HttpServletRequest类型成员,因为我们就要装饰它。 
3.编写我样想覆盖的方法,也就是我们想提供特殊功能的方法。 
举例,上边我们编写的统一WEB编码的filter是存在问题的,如果我们提交一个表单,表单的提交方式为GET,那么我们设置request的编码是不起作用的。所以在这里我们就使用Decorator设计模式来完善统一编码的功能: 
编写自定义类MyServletRequest.java类: 


class MyServletRequest extends HttpServletRequestWrapper { 
// 我们要装饰的对象 
HttpServletRequest myrequest; 
public MyServletRequest(HttpServletRequest request) { 
super(request); 
this.myrequest = request; 

// 我们要增强的功能方法 
@Override 
public String getParameter(String name) { 
// 使用被装饰的成员,获取数据 
String value = this.myrequest.getParameter(name); 
if (value == null) 
return null; 
// 将数据转码后返回 
try { 
value = new String(value.getBytes("ISO8859-1"), "UTF-8"); 
} catch (UnsupportedEncodingException e) { 
e.printStackTrace(); 

return value; 



我们修改Encoding.java过滤器的代码如下: 
复制代码代码如下:

public class Encoding implements Filter { 
public void destroy() { 
// TODO Auto-generated method stub 

public void doFilter(ServletRequest arg0, ServletResponse arg1, 
FilterChain arg2) throws IOException, ServletException { 
arg2.doFilter(new MyServletRequest((HttpServletRequest)request), arg1); 

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


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 黑户急需5万块钱怎么办 家里欠了好多钱怎么办 欠好多网贷我该怎么办 外面欠了很多钱怎么办 欠了好多网贷怎么办 欠那么多钱我该怎么办 急用钱怎么办谁给指条路 晚上睡不着觉怎么办白天又醒不来 胃疼了好几天怎么办 手机移动卡怎么办副卡 大学我好累我怎么办 感觉婚姻很累了怎么办 一个人的心累了怎么办 头被凉水激着了怎么办 人一但懒惰了怎么办 太懒了怎么办都不想活 和老公和不来该怎么办 摩拜忘记关锁怎么办 绿萝叶子变软了怎么办 水痘疫苗打了3次怎么办 免疫组化p16阳性怎么办 乙肝五项25为阳怎么办 苏宁快递丢件了怎么办 新房苯超标10倍怎么办 结婚后遇到真爱怎么办 除皱针眉毛上扬怎么办 玩游戏充钱后悔怎么办 我被欺骗了感情怎么办 有隐私被威胁了怎么办 在微信上被威胁怎么办 别人恐吓我我该怎么办 警属受到威胁该怎么办 出了事故家属闹怎么办 孩子不愿和人交流怎么办 4岁双胞胎说话迟怎么办 三岁宝宝说话迟怎么办 3岁幼儿说话迟钝怎么办 人很迷茫的时候怎么办 人在迷茫的时候怎么办 缺乏安全安感该怎么办 皮球掉进树洞里怎么办