




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
14.1 Servlet过滤器简介 很早之前,ServletAPI就已成为企业应用开发的重要工具。现在,Servlet中的过滤器和监听器功能则是对J2EE体系的一个补充。过滤器使得Servlet开发者能够在请求到达Servlet之前截取请求,在Servlet处理请求之后修改应答;而Servlet监听器可以监听客户端的请求、服务端的操作,通过监听器,可以自动激发一些操作,如监听应用的启动和停止等。本章将接着介绍Servlet过滤器和监听器的相关知识以及在实际开发中如何使用这些技术。本章重点: Servlet过滤器简介 Servlet过滤器的实现 Servlet过滤文本信息 Servlet监听器简介14.1 Servlet过滤器简介Servlet过滤器是小型的Web组件,能拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是封装了一些功能的Web组件,这些功能虽然很重要,但是对于处理客户机请求或发送响应来说不是决定性的。典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性等。一个过滤器可以被关联到任意多个资源,一个资源也可以关联到任意多个过滤器。例如,在图14.1中就有如下的关联关系。 F1同时被关联到S1、S2、S3。 F1、F2、F3都和S2关联。图14.1 Web资源与过滤器相关联关联到同一个资源的过滤器形成一个过滤器链。例如,对S2进行访问时,F1、F2、F3就形成了一个过滤器链,客户要访问资源S2,就要经过F1过滤器,然后是F2、F3,最后才是要访问的资源。如果在经过上面这3个过滤器时出现了错误或者被禁止访问,客户的请求就无法到达资源S2。在Servlet过滤器中,这个过滤器传递的过程是通过FilterChain.dofilter()方法实现的,当过滤器链到达末尾时,这个方法调用请求的资源。建立一个过滤器,一般需要下面4个步骤:(1)建立一个实现Filter接口的类。这个类需要3个方法,即doFilter、init和destroy。doFilter方法包含主要的过滤代码(见第(2)步),在init方法中进行一些初始化的设置,而destroy方法进行清除过滤器占用的资源。(2)在doFilter方法中放入过滤行为。doFilter方法的第一个参数为ServletRequest对象,为过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为FilterChain,用来调用过滤器链中下一个过滤器或者在到达过滤器末尾时调用Servlet或JSP页。(3)调用FilterChain对象的doFilter方法。Filter接口的doFilter方法将一个FilterChain对象作为它的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另一个过滤器与Servlet或JSP页面关联,则Servlet或JSP页面被激活。(4)对相应的Servlet和JSP页面注册过滤器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素对需要进行过滤的资源进行配置。14.2 实现一个Servlet过滤器Servlet过滤器API包含3个简单的接口,即Filter、FilterChain和FilterConfig,它们位于javax.servlet包中。从编程的角度看,过滤器类将实现Filter接口,然后使用这个过滤器类中的FilterChain和FilterConfig接口。该过滤器类的一个引用将传递给FilterChain对象,以允许过滤器将控制权传递给过滤器链中的下一个过滤器或者资源。FilterConfig对象将由容器提供给过滤器,以允许访问该过滤器的初始化数据。14.2.1 编写实现类的程序下面是一个简单的Servlet过滤器的例子,其中将获取一个Web服务器给客户提供服务需要的时间,也就是响应时间。【本节示例参考:资料光盘源代码第14章14-2Servlet.java】【实例14-1】这是一个实现类的程序,主要是使用过滤器处理请求,在处理时可能要耗费很多 时间。程序14-1 Servlet.java01 package cn.ac.ict.Filter;02 import java.io.IOException;03 import java.io.PrintWriter;04 import java.io.StringWriter;05 import java.util.Date;06 import javax.servlet.*;07 public class ResponseTimeFilter implements Filter 08 private FilterConfig filterConfig = null;09 public void init(FilterConfig config) throws ServletException /初始化函数10 this.filterConfig = config;11 12 public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException 13 Date startTime, endTime;14 double totalTime;15 startTime = new Date();16 StringWriter sw = new StringWriter();17 PrintWriter writer = new PrintWriter(sw);18 writer.println();19 writer.println(ResponseTimeFilter Before call chain.doFilter);20 chain.doFilter(request, response); /将请求转发给过滤器链中下一个资源21 /下面是资源的响应时间22 /下面计算开始时间和结束时间的差,也就是响应时间23 endTime = new Date();24 totalTime = endTime.getTime() - startTime.getTime();25 totalTime = totalTime / 1000; /将毫秒时间转换为以秒为单位26 writer.println(ResponseTimeFilter Before call chain.doFilter);27 writer.println(=);28 writer.println(Total elapsed time is: + totalTime + seconds. );29 writer.println(=);30 filterConfig.getServletContext().log(sw.getBuffer().toString(); /将信息输出到日志中31 writer.flush();32 33 public void destroy() 34 this.filterConfig = null;35 36 public FilterConfig getFilterConfig() 37 return null;38 39 public void setFilterConfig(FilterConfig config) 40 41 【深入学习】当容器第一次加载该过滤器时,init()方法将被调用。该类在这个方法中包含了一个指向FilterConfig对象的引用。过滤器的大多数时间都消耗在执行过滤操作上,第20行中的doFilter()方法被容器调用,同时传入分别指向这个请求/响应链中的ServletRequest、ServletResponse和FilterChain对象的引用。然后过滤器就有机会处理请求,将处理任务传递给链中的下一个资源(通过调用FilterChain对象引用上的doFilter()方法),之后在处理控制权返回该过滤器时处理响应。14.2.2 配置发布Servlet过滤器发布Servlet过滤器时,必须在web.xml文件中加入和元素,其中,元素用来定义一个过滤器,在本例中使用了如下代码: Request Response Time cn.ac.ict.Filter.ResponseTimeFilter 以上代码中,指定过滤器的名字,指定过滤器的完整类名,也可以在元素中内嵌元素来为过滤器提供初始化参数。元素用于将过滤器和URL关联,本例中的代码如下: Request Response Time /ShowCounter.jsp 当客户请求的URL和指定的URL相匹配时,就会触发ResponseTimeFilter过滤器,这里的元素的值和元素中的值应该相同。说明:如果希望Servlet过滤器能过滤所有的客户请求,可以将的值设置为/*。准备好上面的文件后,按照如下步骤即可发布这个Servlet过滤器。(1)编译ResponseTimeFilter类,编译时,需要将Java Servlet API的包servlet-api.jar放到类路径中,编译后的类放到本章Web应用的WEB-INFclasses目录下,并且目录结构要与包的结构一致。(2)在web.xml文件中按照上面说明的方法配置这个过滤器。(3)为了观察这个过滤器的日志,应确保在server.xml文件的localhost对应的host元素中配置了如下的logger元素: 以上内容在默认情况下都是配置好的。(4)启动Tomcat,在浏览器地址栏中输入http:/localhost:8080/14/ShowCounter.jsp,这时在logs localhost_log.2009-05-24.txt文件中会生成如下的日志信息:2009-05-26 23:03:42 StandardContext/15ResponseTimeFilter Before call chain.doFilterResponseTimeFilter Before call chain.doFilter=Total elapsed time is: 0.0 seconds.=说明:本例中访问的ShowCounter.jsp页面在本章的监听器部分介绍,如果读者不想跳跃着查看这个文件,可以尝试修改过滤器关联的URL,使得它可以过滤读者指定的资源。14.3 ServletRequest和ServletResponse的包装类Servlet过滤器能够对客户的请求和响应进行包装,并根据自定义的行为对请求和响应进行修改,这就是通过使用ServletRequest和ServletResponse的包装类HttpServletRequestWrapper和HttpServletResponseWrapper类来实现的。这两个类提供了所有request和response方法的默认实现,并且默认地代理了所有对原有request和response的调用。这也意味着,要改变一个方法的行为只需要从封装类继承并重新实现一个方法即可。 ServletRequestWrapper类:是ServletRequest的包装类,实现了ServletRequest接口,并对其方法提供了默认实现。 ServletResponseWrapper类:是ServletResponse的包装类,实现了ServletResponse接口,并对其方法提供了默认实现。14.4 用Servlet过滤器过滤文本信息在14.3节中简单介绍了ServletRequest和ServletResponse的包装类,它们在过滤器设计中会经常被用到。本节将介绍一个使用HttpServletResponseWrapper类的例子,客户输入的内容会被检查,如果存在不允许出现的信息,就会被过滤掉,而被替换成其他的字符。在这个例子中,客户输入用户名并发布自己的留言信息,然后提交给服务器,服务器再将这些信息反馈给客户。如果客户的留言中有指定的字符串,就会调用过滤器将这个字符串替换掉。14.4.1 输出流管理类在Servlet输出时可以选择不同的输出流,将它们集合在一起,即可很容易地对这些流进行管理,使用时也会更方便。如何使用输出流管理类,可以看下面的代码。【本节示例参考:资料光盘源代码第14章14-4ByteArrayPrintWriter.java】【实例14-2】将输出流进行方法的实例化,方便以后程序的调用。程序14-2 ByteArrayPrintWriter.java01 package cn.ac.ict;02 import java.io.ByteArrayOutputStream;03 import java.io.PrintWriter;04 import javax.servlet.ServletOutputStream;05 public class ByteArrayPrintWriter 06 private ByteArrayOutputStream baos = new ByteArrayOutputStream();07 private PrintWriter pw = new PrintWriter(baos);08 private ByteArrayOutputStream sos = new ByteArrayOutputStream();09 public ByteArrayPrintWriter(ByteArrayOutputStream aos) 10 this.baos = aos;11 12 /一个为空的构造方法13 public ByteArrayPrintWriter() 14 15 /使用字符输出流时调用获取输出流16 public PrintWriter getWriter() 17 return pw;18 19 /使用字节输出流时调用获取输出流20 public ByteArrayOutputStream getStream() 21 return sos;22 23 byte toByteArray() 24 return baos.toByteArray();25 26 【深入学习】在第6、7、8行共定义了3个对象,一个是用字符流输出的,一个是用字节流输出的,但是它们最终都套接到类型为ByteArrayOutputStream的对象上,这个对象为它们提供了原始输出数据。14.4.2 编写Servlet过滤器前面编写了需要使用的辅助类,接下来即可开发进行实际过滤功能的文本过滤器。【本节示例参考:资料光盘源代码第14章14-4TextModifierFilter.java】【实例14-3】如何实现文本过滤器,代码(TextModifierFilter.java)如下:程序14-3 TextModifierFilter.java01 package cn.ac.ict;02 import java.io.IOException;03 import java.io.PrintWriter;04 import java.util.Locale;05 import javax.servlet.Filter;06 import javax.servlet.FilterChain;07 import javax.servlet.FilterConfig;08 import javax.servlet.ServletException;09 import javax.servlet.ServletOutputStream;10 import javax.servlet.ServletRequest;11 import javax.servlet.ServletResponse;12 import javax.servlet.http.HttpServletRequest;13 import javax.servlet.http.HttpServletResponse;14 import ernal.ws.util.ByteArrayBuffer;15 public class TextModifierFilter implements Filter, ServletResponse 16 private FilterConfig filterConfig;17 private String searchStr;18 private String replaceStr;19 public void init(FilterConfig config) throws ServletException 20 this.filterConfig = config;21 /初始化要查找的字符串和替换后的字符串的值22 this.searchStr = search;23 this.replaceStr = replace;24 25 public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException 26 HttpServletRequest hsr = (HttpServletRequest)request;27 final HttpServletResponse resp = (HttpServletResponse)response;28 final ByteArrayBuffer pw = new ByteArrayBuffer();29 /构造响应包装类30 TextModifierFilter tmrw = new TextModifierFilter();31 filterConfig.getServletContext().log(TextModifierFilter:Before call chain.doFilter);32 /将请求转发给Servlet,并获取响应33 chain.doFilter(request,tmrw);34 /下面的代码检查响应并对需要替换的字符进行替换35 /将响应转化为byte数组36 byte bytes = pw.toByteArray();37 if (bytes = null | (bytes.length = 0) 38 filterConfig.getServletContext().log(No content!);39 40 /将其转换为字符串便于查找41 String content = new String(bytes);42 String searchcontent = (new String(bytes).toLowerCase();43 /查找指定字符出现的第一个位置44 int endPos = searchcontent.indexOf(this.searchStr);45 String returnStr;46 /响应中包含这样一个字符串47 if(endPos!=-1)48 String front_part_Str = content.substring(0,endPos);49 returnStr=front_part_Str+this.replaceStr+content.substring (endPos + this.searchStr.length();50 else51 /响应中不包含这样一个字符串52 returnStr = content;53 54 resp.setContentLength(returnStr.length();55 resp.getOutputStream().write(returnStr.getBytes();56 filterConfig.getServletContext().log(TextModifierFilter:After call chain.doFilter);57 58 public void destroy() 59 this.filterConfig = null;60 61 public FilterConfig getFilterConfig() 62 return null;63 64 public void setFilterConfig(FilterConfig config) 65 66 public void flushBuffer() throws IOException 67 68 public int getBufferSize() 69 return 0;70 71 public String getCharacterEncoding() 72 return null;73 74 public String getContentType() 75 return null;76 77 public Locale getLocale() 78 return null;79 80 public ServletOutputStream getOutputStream() throws IOException 81 return null;82 83 public PrintWriter getWriter() throws IOException 84 return null;85 86 public boolean isCommitted() 87 return false;88 89 public void reset() 90 91 public void resetBuffer() 92 93 public void setBufferSize(int arg0) 94 95 public void setCharacterEncoding(String arg0) 96 97 public void setContentLength(int arg0) 98 99 public void setContentType(String arg0) 100 101 public void setLocale(Locale arg0) 102 103 【深入学习】上述代码的主要功能集中在第25行中的doFilter()方法中,在这个方法中构造了一个响应包装器。当调用chain.doFilter(request,tmrw)方法时,Servlet的响应都已经在响应包装器对象tmrw中了,之后即可调用相关的方法获取响应的内容,并进行适当的处理。14.4.3 编写JSP和Servlet文件前面已经开发完成了一个完整的文本过滤器的程序,这里将接着开发演示过滤器工作过程的JSP和Servlet文件。【本节示例参考:资料光盘源代码第14章14-4textModifier.jsp】【实例14-4】实现一个过滤器的程序,查看它的工作过程。首先来看利用JSP文件实现的代码。程序14-4 textModifier.jsp01 02 03 04 User Message05 06 11 12 13 14 15 16 17 User Message18 19 20 21 22 23 24 UserName25 26 27 28 29 30 31 32 Message:33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 下面是用户提交输入留言信息的响应Servlet,其代码如下:TextModiferServlet.java01 package cn.ac.ict;02 import java.io.IOException;03 import javax.servlet.ServletException;04 import javax.servlet.ServletOutputStream;05 import javax.servlet.http.HttpServlet;06 import javax.servlet.http.HttpServletRequest;07 import javax.servlet.http.HttpServletResponse;08 public class TextModiferServlet extends HttpServlet 09 protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throws ServletException, IOException 10 /设置响应的类型11 response.setContentType(text/html;charset=gb2312);12 ServletOutputStream out = response.getOutputStream();13 /获取请求参数14 String user = request.getParameter(username);15 String content = request.getParameter(content);16 String outstr = ;17 if (user != null) 18 user = new String(user.getBytes(ISO8859-1), GB2312);19 20 if (content != null) 21 content = new String(content.getBytes(ISO8859-1), GB2312);22 23 if (user != null) & (content != null) 24 outstr = User + user + say: + content + ;25 26 out.println(rn);27 out28 .println(rn);29 out.println(rn);30 out.println(rn);31 out.println(User Messagern);32 out.println(rn);33 out.println(rn);38 out.println(rn);39 out.println(rn);40 out.println(rn);41 out.println(rn);42 out.println(rn);43 out.println(UserMessage rn);44 out.println( + outstr + rn);45 out.println(rn);46 out.println(UserNamern);47 out.println(rn);48 out.println(rn);49 out.println(rn);50 out.println(Message:rn);51 out.println( rn);52 out.println(rn);53 out.println(rn);54 out.println( rn);55 out.println( rn);56 out.println(rn);57 out.println(rn);58 out.println(rn);59 out.println(rn);60 out.println(rn);61 out.println(rn);62 out.println(rn);63 out.println(rn);64 out.println(rn);65 out.println(rn);66 out.println();67 68 protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throws ServletException, IOException 69 doGet(request, response);70 71 【运行程序】准备好所有需要使用的文件后,可以按照如下步骤发布这个Web应用。(1)编译输出流管理类、响应包装器和过滤器的Java程序。编译时需要将servlet-api.jar放到类路径中,编译完成后,将得到的字节码文件复制到Web应用的WEB-INFclasses目录下,存放位置与包的结构一致。(2)在Web应用的web.xml文件中配置使用的Servlet和Servlet过滤器,也就是在web.xml文件中添加如下代码:01 02 03 textModifier 04 cn.ac.ict.Servlet.TextModiferServlet05 06 0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 城市交通可持续发展与管理模式探索
- 公司报销合同(标准版)
- 玉米购种合同(标准版)
- 更改买房合同(标准版)
- 龙村建房申请报告(3篇)
- 芝华士合同(标准版)
- Dimethyl-tetrasulfide-1-4-Dimethyltetrasulfane-生命科学试剂-MCE
- Decloxizine-dihydrochloride-Standard-生命科学试剂-MCE
- 城市地下综合管廊智慧运维:2025年技术创新与市场前景可行性分析
- 件杂货运输合同(标准版)
- 耕地占用税培训课件
- 石灰石石膏湿法脱硫工艺详1系统课件
- 组织行为学核心主题全系列(MBA研修班学生版4日)课件
- 局部解剖学绪论课件
- 可持续发展旅游课件
- 桥梁基础工程施工
- 非常实用的鸡的解剖课件
- 始祖鸟新员工基础知识考试(NEW)试题含答案
- 渣浆泵基础知识课件
- 上海印象上海介绍课件PPT模板
- 布赫液压样本
评论
0/150
提交评论