Servlet过滤器和监听器.doc_第1页
Servlet过滤器和监听器.doc_第2页
Servlet过滤器和监听器.doc_第3页
Servlet过滤器和监听器.doc_第4页
Servlet过滤器和监听器.doc_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第13章 Servlet过滤器和监听器Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤、判断用户的登录状态。过滤器使得Servlet开发者能够在客户端请求到达Servlet资源之前被截获,在处理之后再发送给被请求的Servlet资源,并且还可以截获响应,修改之后再发送给用户。而Servlet监听器可以监听客户端发出的请求、服务器端的操作,通过监听器,可以自动激发一些操作,如监听在线人数。Servlet过滤器和监听器都是Servlet 2.3规范中最主要的新增功能。13.1 Servlet过滤器简介绍Servlet过滤器是在Java Servlet 2.3 规范中定义的,它是一种可以插入的Web组件,它能够对Servlet 容器的接收到的客户端请求和向客户端发出的响应对象进行截获,过滤器支持对Servlet程序和JSP页面的基本请求处理功能,如日志、性能、安全、会话处理、XSLT转换等。Servlet过滤器本身不产生请求和响应,它只提供过滤作用,Servlet过滤器能够在Servlet程序(JSP页面)被调用之前检查request对象,修改请求头和请求内容,在Servlet程序(JSP页面)被调用之后,检查response对象,修改响应头和响应内容。13.1.1 Servlet过滤器的特点1.Servlet过滤器可以检查和修改request和response对象。 2.Servlet过滤器可以被指定与特定的URL关联,只有当客户请求访问该特定的URL时,才会触发过滤器。3.Servlet过滤器可以被串联成串,形成过滤链,协同修改请求和响应。13.1.2 Servlet过滤器的适用场合Servlet过滤器适用于下列场合:1.认证过滤 2.登录和审核过滤 3.图象转换过滤 4.数据压缩过滤 5.加密过滤 6.令牌过滤 7.资源访问触发事件过滤8.汉字乱码过滤13.1.3 Servlet过滤器的作用Servlet过滤器的作用如下:1.查询请求并作出相应的行动。2.阻塞请求-响应对,使其不能进一步传递。3.修改请求头和内容,用户可以提供自定义的请求。4.修改响应头和内容,用户可以通过提供定制的响应版本实现。5.与外部资源进行交互。13.2 Servlet过滤器的体系结构Servlet过滤器用于拦截传入的请求和传出的响应,并监视、修改或以某种方式处理正在通过的数据流。Servlet过滤器是自包含、模块化的组件,可以将它们添加到请求/响应过滤链中,或者在不影响应用程序中其它Web组件的情况下删除它们。Servlet过滤器只在改动请求和响应的运行时处理,因而不应该将它们之间嵌入到Web应用程序框架,除非是通过Servlet API中良好定义的标准接口来实现。Web资源可以配置成为没有过滤器与之关联(默认情况)、与单个过滤器关联(典型情况),甚至是与一个过滤器链关联。其功能与Servlet一样,主要是接收请求和响应对象,然后过滤器会检查请求对象,并决定是将该请求转发给链中的下一个过滤器,还是终止该请求并直接向客户端发会一个响应,如果请求被转发了,它将被传递给过滤链中的下一个过滤器,或者Servlet程序(JSP页面),在这个请求通过过滤器链并被服务器处理后,一个响应将以相反的顺序通过该过滤链发送回去,这样就给每个Servlet过滤器提供了根据需要处理响应对象的机会。当过滤器在Servlet 2.3规范中首次引入时,只能过滤客户端和客户端所访问的指定Web资源之间的内容(请求/响应),如果该Web资源将请求转发给其它Web资源时,那就不能向幕后委托的任何请求应用过滤器。Servlet 2.4 规范消除了这个限制,Servlet过滤器现在可以应用于J2EE Web环境中存在请求和响应的任何地方。可见,Servlet过滤器可以应用在客户端和Servlet程序之间、Servlet程序和Servlet程序之间、Servlet程序和JSP页面之间、JSP页面和JSP页面之间,具有强大的能力和灵活性。13.2.1 Servlet过滤器对请求的过滤Servlet过滤器对请求的过滤过程如下:1.Servlet容器创建一个Servlet过滤器实例。2.Servlet过滤器实例调用init()方法得到初始化参数。3.Servlet过滤器实例调用doFilter()方法,根据初始化参数的值判断该请求是否合法,如果该请求不合法,则阻塞该请求,如果是合法请求,则调用chain.doFilter(request,response)方法将该请求向后转发。13.2.2 Servlet过滤器对响应的过滤Servlet过滤器对响应的过滤过程如下:1.过滤器截获客户端的请求。2.重新封装ServletResponse,在封装后的ServletResponse中提供客户端自定义的输出流。3.将请求向后转发。4.Web组件产生响应。5.过滤器从被封装的ServletResponse中获取客户自定义的输出流。6.将响应内容通过客户自定义的输出流写入缓冲流。7.在缓冲流中修改响应内容后清空缓冲流,输出响应内容。13.2.3 Servlet过滤器的发布 Seevlet过滤器设计完毕之后,必须对该过滤器进行发布(配置),发布一个Servlet过滤器时,必须在项目的web.xml文件中加入元素和元素,元素用来定义一个过滤器,该元素的属性有: 属性描述filter-name指定过滤器的名字filter-class指定过滤器类init-param指定过滤器的初始化参数元素用于将过滤器与URL关联,其属性有: 属性描述filter-name指定过滤器的名字url-pattern指定与过滤器关联的URL13.3 实现一个Servlet过滤器13.3.1 Servlet过滤器接口的构成所有的Servlet过滤器都必须实现javax.servlet.filter接口,该接口中定义了3个过滤器必须实现的方法:1.void init(FilterConfig):过滤器的初始化方法,Servlet容器在创建过滤器实例时调用这个方法,在这个方法中可以读出在web.xml文件中为该过滤器配置的初始化参数。2.void doFilter(ServletRequest,ServletResponse,FilterChain):用于完成实际的过滤操作,当客户请求访问与过滤器相关联的URL时,Servlet容器将先调用过滤器的这个方法,FilterChain参数用于访问后续过滤器。3.void destroy():过滤器在被取消前执行这个方法,释放过滤器申请的资源。13.3.2 Servlet过滤器的创建步骤创建一个Servlet过滤器需要下面的步骤: 1.创建一个实现了javax.servlet.Filter接口的类。2.重写init(FilterConfig)方法,读入为过滤器配置的初始化参数,申请过滤器需要的资源。3.重写方法doFilter(ServletRequest,ServletResponse,FilterChain),完成过滤操作,可以从ServletRequest参数中得到全部的请求信息,从ServletResponse参数中得到全部的响应信息。4.在doFilter()方法的最后,使用FilterChain参数的doFilter()方法将请求和响应后传。5.对响应的Servlet程序和JSP页面注册过滤器,在部署描述文件(web.xml)中使用和元素对过滤器进行配置。13.3.3 编写过滤器类在过滤器中,需要使用3个简单的接口,它们是:分别是Filter、FilterChain、FilterConfig,全部包含在javax.servlet包中。从编程的角度看,过滤器类要实现Filter接口,然后使用实现了FilterChain和FilterConfig接口的对象来工作,FilterChain对象负责将请求和响应后传,FilterConfig对象负责为过滤器读初始化参数。为了与过滤器的三步模式(创建、工作、撤消)保持一致,过滤器必须重写Filter接口中的三个方法:init():在容器实例化过滤器市时被调用,主要为过滤器做初始化,该方法有一个FilterConfig类型的形参。doFilter():这个方法用来完成真正的过滤操作,它有3个形式参数:ServletRequest参数包含请求信息,ServletResponse参数包含响应信息,FilterChain参数用来将请求和响应向后传递。destroy():过滤器被撤消时调用这个方法,释放过滤器所 占有的资源。在下面的例子中实现了一个简单的Servlet过滤器(SessionFilter.java),它实现的功能是判断客户是否成功登录,如果成功登录,转向正确页面,否则返回一个错误页面,提示客户应该进行登录。该过滤器代码如下:/includeList:数组,受保护的资源。/logonList:数组,登录页面。package ch13;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;public class SessionFilter implements FilterString logonStrings,includeStrings,redirectPath,disabletestfilter;String logonList,includeList;private boolean isContains(String containers,String regx) boolean result=false;for(int i=0;iregx.length;i+) if (containers.indexOf(regxi)!=-1)return true;return result;public FilterConfig config;private void setFilterConfig(FilterConfig config) this.config=config;private FilterConfig getFilterConfig()return config;/必须重写public void init(FilterConfig filterConfig) throws ServletExceptionthis.config=filterConfig;logonStrings=config.getInitParameter(logonStrings); includeStrings=config.getInitParameter(includeStrings); redirectPath=config.getInitParameter(redirectPath); disabletestfilter=config.getInitParameter(disabletestfilter);logonList=logonStrings.split(;);/分割为数组 includeList=includeStrings.split(;);/分割为数组/必须重写public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws ServletException, IOException HttpServletRequest httpreq=(HttpServletRequest)request;HttpServletResponse httpres=(HttpServletResponse)response;HttpServletResponseWrapper wrapper=new HttpServletResponseWrapper(HttpServletResponse)response);if (disabletestfilter.toUpperCase().equals(Y)chain.doFilter(request,response);/如果不过滤return;Object user=httpreq.getSession().getAttribute(userinfo);if (user=null)/该用户没有登录if (!isContains(httpreq.getRequestURI(),includeList)chain.doFilter(request,response);return;/访问的是不受保护的页面,可以if (isContains(httpreq.getRequestURI(),logonList)chain.doFilter(request,response);return; /访问的是登录页面,可以wrapper.sendRedirect(redirectPath); /转向登页面 else /该用户已经登录chain.doFilter(request,response);/必须重写public void destroy() config=null;在上面的这个Servlet过滤器程序中,根据用户session对象中有无userinfo这个属性来确定该用户是否已经登录。13.3.4 配置部署过滤器在WEB-INF/web.xml文件中用以下代码配置过滤器:SessionFilterch13.SessionFilter logonStringsLogin.jsp includeStrings.jsp;.html;.htm redirectPath./Login.jsp disabletestfiltern SessionFilter/*在上面的配置中,参数logonStrings指定可以访问的登录页面,参数includeStrings指定受保护的资源的后缀,参数redirectPath表示没有登录时转向的登录页面,参数disabletestfilter表示过滤器是否有效。而 /* 表示过滤器与所有的URL都关联(对所有的访问请求都进行过滤)。在浏览器中访问任意的资源时,都要通过这个过滤器的过滤。13.4 过滤器的应用案例13.4.1 版权过滤器的应用案例在一个Web应用中的所有页面的下面添加上版权信息,通常的做法是采用指令或 标签,使用过滤器也是一个好办法。1.编写过滤器类CopyrightFilter.javapackage ch13;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;public class CopyrightFilter implements Filterprivate String date;public FilterConfig config;/必须重写public void init(FilterConfig filterConfig) throws ServletExceptionthis.config=filterConfig;date=config.getInitParameter(date);/必须重写public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws ServletException, IOException chain.doFilter(request,response);PrintWriter out=response.getWriter();out.print(版权所有:北京工业大学);if (date!=null) out.print(+date+);out.flush();/必须重写public void destroy() config=null;在这个过滤器中,在doFilter()方法的最后,通过response对象得到一个输出流out,然后通过输出流向客户端输出版权信息,这样,每个页面的最后都会出现过滤器添加的版权信息。2.修改web.xml,配置该过滤器CopyrightFilterch13.CopyrightFilter date2010-9 CopyrightFilter/*3.测试在浏览器中任意访问一个页面,都可以在看到在页面的下部出现过滤器添加的版权信息。13.4.2 禁止未授权的IP访问站点过滤器的应用案例使用过滤器禁止未授权的IP访问站点是过滤器常见的应用,本例演示了如何利用过滤器实现禁止未授权的IP访问站点。1.编写过滤器类FilterIP.javapackage ch13;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;public class FilterIP implements Filterprivate String filterIP,error;public FilterConfig config;/必须重写public void init(FilterConfig filterConfig) throws ServletExceptionthis.config=filterConfig;filterIP=config.getInitParameter(FilterIP);if (filterIP=null) filterIP=;error=config.getInitParameter(ERROR);if (error=null) error=error.jsp;/必须重写public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws ServletException, IOException RequestDispatcher dispatcher=request.getRequestDispatcher(ErrorInfo.jsp);String remoteIP=request.getRemoteAddr();/得到客户的IP地址if (remoteIP.equals(filterIP) dispatcher.forward(request,response);return; elsechain.doFilter(request,response);/必须重写public void destroy() config=null;在这个过滤器中,在doFilter()方法内,通过request对象得到客户端的IP地址,如果客户端的IP是被禁止的IP,则使用request对象将请求转发给一个出错页面。2.修改web.xml,配置过滤器FilterIPch13.FilterIP FilterIP ERRORerror.jsp FilterIP/*对来自的客户的所有请求(/*)都进行过滤,转移到error.jsp页面。3.编写出错页面error.jsp网站不允许IP地址为的计算机访问。在IP地址为 的计算机上访问网站的任何一个资源,都会转移到error.jsp页面。13.4.3 过滤页面内容(响应内容)本过滤器使用HttpServletResponseWrapper类来实现页面内容的过滤,它的原理是让Web资源先将页面内容(响应内容)写入到HttpServletResponseWrapper对象中,然后再在过滤器中处理HttpServletResponseWrapper对象中的页面内容(响应内容),最后再将处理好的页面内容(响应内容)发送给客户。1.编写HttpServletResponseWrapper类的子类.javapackage ch13;import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper;import javax.servlet.ServletOutputStream;public class WrapperResponse extends HttpServletResponseWrapper public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2; private int outputType = OT_NONE; private ServletOutputStream output = null; private PrintWriter writer = null; private ByteArrayOutputStream buffer = null; /构造函数 public WrapperResponse(HttpServletResponse resp) throws IOException super(resp); buffer = new ByteArrayOutputStream(); /得到字符输出流public PrintWriter getWriter() throws IOException if (outputType = OT_STREAM) throw new IllegalStateException(); /已经用了OutputStream流else if (outputType = OT_WRITER) return writer; else outputType = OT_WRITER; writer = new PrintWriter(new OutputStreamWriter(buffer,getCharacterEncoding(); return writer; /得到字节输出流public ServletOutputStream getOutputStream() throws IOException if (outputType = OT_WRITER) throw new IllegalStateException(); /已经用了Writer流else if (outputType = OT_STREAM) return output; else outputType = OT_STREAM; output = new WrappedOutputStream(buffer); return output; /刷新输出内容public void flushBuffer() throws IOException if (outputType = OT_WRITER) writer.flush(); if (outputType = OT_STREAM) output.flush(); /输出缓冲区复位public void reset() outputType = OT_NONE; buffer.reset(); public String getResponseData() throws IOException flushBuffer(); return new String(buffer.toByteArray(); /内部类,将数据写入自己的定义的缓冲区class WrappedOutputStream extends ServletOutputStream private ByteArrayOutputStream buffer; public WrappedOutputStream(ByteArrayOutputStream buffer) this.buffer = buffer; public void write(int b) throws IOException buffer.write(b); public byte toByteArray() return buffer.toByteArray(); 在这个类中,一定要重写response对象的关于输出流(outputStream、writer)操作的方法:getOutputStream()、getWriter()、flushBuffer()、reset()。2.编写过滤器GavinFilter.javapackage ch13;import java.io.IOException; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class GavinFilter implements Filter private String oldword=% , newword=百分号; public void destroy()public void doFilter(ServletRequest request, ServletResponse response, FilterChainchain) throws IOException, ServletException HttpServletResponse oldresponse = (HttpServletResponse)response; WrapperResponse wrapperResponse = new WrapperResponse(oldresponse); chain.doFilter(request, wrapperResponse); /让服务器将响应内容写到Wrapper中String html = wrapperResponse.getResponseData(); /取出响应内容oldresponse.getWriter().print(html.replaceAll(oldword, newword); /替换页面中的文字,然后发送给客户 public void init(FilterConfig config) throws ServletException oldword=config.getInitParameter(oldword);newword=config.getInitParameter(newword); 该过滤器将页面内容(响应内容)中的字符 % 替换为百分号三个汉字,由此可见,实现了对响应内容的过滤。 3.对该过滤器的配置 gavinFilter ch13.GavinFilter oldword % newword 百分号 gavinFilter /* 13.5 Servlet监听器Servlet监听器也叫做listener,通过它可以监听Web应用的上下文(环境)信息、Servlet请求信息、Servlet会话信息,并自动根据不同情况,在后台调用相应的处理程序。通过监听器,可以自动激发一些操作,比如监听在线人数,当增加一个HttpSession时就激发sessionCreated(HttpSessionEvent)方法,这样就可以给在线人数加1。13.5.1 监听器的原理Servlet监听器是Web应用开发的一个重要组成部分,Servlet监听器是在Servlet2.3规范中和Servlet过滤器一起引入的。在 Servlet2.4 规范中对其进行了比较大的改进。主要就是用来对Web应用进行监督和控制,极大地增强了Web应用的事件处理能力。Servlet监听器的功能比较类似于Java中的GUI程序的监听器,可以监听由于Web应用中的状态改变而引起的Servlet容器产生的相应事件,然后接收并处理这些事件。13.5.2 监听器的类型在 Servlet 2.4 规范中,根据监听对象的类型和范围,将监听器分为3类:ServletRequest监听器(请求监听器)、HttpSession监听器(会话监听器)、ServletContext监听器(上下文监听器),其中请求监听器(ServletRequest监听器)是 Servlet 2.4 规范中新增加的监听器,可以用来监听客户的端请求,在Servlet 2.4 规范中包含了8个监听器接口和6个监听器事件类,具体的监听器接口和事件如下表: 监听对象监听接口监听事件ServletRequestServletRequestListener(2个方法)ServletRequestEventServletRequestAttributeListener(3个方法)ServletRequestAttributeEventHttpSessionHttpSessionListener(2个方法)HttpSessionEventHttpSessionActivationListener(2个方法)HttpSessionAttributeListener(3个方法)HttpSession

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论