11Listener和Filter

Listener
Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。Javax.servlet中定义了三类监听器:ServletContex相关、ServletRequest相关、和HttpSession相关的监听器。


ServletContext相关监听器:
ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
void attributeAdded(ServletContextAttributeEvent scab):在servlet上下文增加了一个属性时触发;
void attributeRemoved(ServletContextAttributeEvent scab):在servlet上下文移除一个已存在的属性时触发;
void attributeReplaced(ServletContextAttributeEvent scab):在servlet上下文替换一个已存在的属性时触发。


ServletContextListener监听ServletContext。接收到web应用中servlet上下文载入或销毁的事件通知。
当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;所有的ServletContextListener都将先于filter和servlet的初始化前被通知。
当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。所有的filter和servlet都将在ServletContextListener被通知前被destory。


事实上,contextListener、filter、servlet的初始化顺序依次是listener、filter、servlet。




ServletRequest相关监听器
ServletRequestListener:当你希望接收到各种request请求进入(coming in)或离开(out of)一个web部件(component)的消息时,你可以通过实现这个接口来完成。当一个request开始进入每一个web应用的第一个servlet或filter时,将触发进入(coming in)web应用事件,当一个request离开最后一个servlet或filter链的第一个filter时,将触发一个离开(out of)web应用事件。(注意filter链的执行顺序)
该监听器定义了下面两个方法:
void requestDestroyed(ServletRequestEvent sre): request将离开一个web应用;
void requestInitialized(ServletRequestEvent sre) :request 将进入一个web应用。


ServletRequestAttributeListener:当你希望接收到request的属性变更事件时,可以通过实现这个接口来完成。变更通知只在request处于web应用中的时候发出。Request处于一个web应用指的是,从一个request进入(coming in)web应用到离开(out of)web应用之间的时间。
该监听器定义了下面方法:
void attributeAdded(ServletRequestAttributeEvent srae): 向一个request里面增加一个属性时触发;
void attributeRemoved(ServletRequestAttributeEvent srae): 从一个request里面移除一个属性时触发;
void attributeReplaced(ServletRequestAttributeEvent srae): 从一个request里面替换一个属性时触发。




HttpSession相关监听器:
HttpSessionListener监听HttpSession的操作。
当创建一个Session时,激发session Created(HttpSessionEvent se)方法;
当销毁一个Session时,激发sessionDestroyed(HttpSessionEvent se)方法。


HttpSessionAttributeListener监听HttpSession中的属性的操作。
当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;
当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;
当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。




如何指定应用事件监听程序
应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内,listener-class元素列出监听程序的完整的限定类名,如下所示:
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
虽然listener元素的结构很简单,但请不要忘记,必须正确地给出web-app元素内的子元素的次序。
*******************
listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外,因为应用生存期监听程序是serlvet规范的2.3版本中的新内容,所以必须使用 web.xml DTD的2.3版本,而不是2.2版本。
*******************
例如,程序清单5-20给出一个名为ContextReporter的简单的监听程序,它实现了ServletContextListener接口,只要Web应用的Servlet-Context建立(如装载Web应用)或消除(如服务器关闭)时,它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。
程序清单5-20 ContextReporterjava
package moreservlets;


import javax.servlet.*;
import java.util.*;
public class ContextReporter implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
//ServletContextEvent的实例的getServletContext()方法返回SevletContext对象
ServletContext servletContext = event.getServletContext();


System.out.println("Context created on " +
new Date() + ".");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Context destroyed on " +
new Date() + ".");
}
}
程序清单5-21 web.xml(声明一个监听程序的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<filter-mapping> … </filter-mapping>
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
<servlet> ... </servlet>
<!-- ... -->
</web-app>


Filter
Servlet过滤器是小型的Web组建,它可以拦截请求和响应,以便查看,提取或以某种方式操作正在客户机和服务器之间交换的数据。我们可以用过滤器解决中文编码问题。它先于与之相关的servlet或jsp页面运行在服务器上,过滤器可以附加到一个或多个servlet或jsp页面上,并且可以检查进入这些资源的请求信息。过滤器可以做如下选择:
以常规的方式调用资源(即调用servlet或jsp页面)
利用修改过的请求信息调用资源。
调用资源,但在发送响应道客户机前对其进行修改。
组织该资源调用,代之以转到其他的资源。


过滤器通过Web部署描述文件web.xml中的XML元素来声明,这样允许添加和删除过滤器,而无需改动任何应用程序代码或JSP页面。
过滤器首先是根据url-pattern来判断是用哪个过滤器,
如果url-pattern符合多个过滤器的时候,就根据过滤器在web.xml中配置的先后顺序来依次执行过滤器。


如何实现Filter
要想开发一个过滤器,就必须实现javax.servlet.Filter接口,在Filter接口中定义了init,doFilter,destroy方法。下面是一个过滤器走过的流程:
init(FilterConfig filterConfig)
这个方法由Web容器在过滤器实例化之后被调用。用于执行本过滤器的初始化操作,通过参数FilterConfig可以得到这个过滤器的所有配置的参数。它只在此过滤器第一次初始化时执行,不是每次调用过滤器都执行它。FilterConfig对象具有一个getInitParameter方法,它能够访问部署描述符文件(web.xml)中分配的过滤器初始化参数。 




doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
在该方法放入过滤行为,由链路终端用户请求,Web容器将会在每个request/reponse链路中调用doFilter()方法。通过传递FilterChain对象,doFilter()方法可以将request和reponse对象传递到链路中的下一个实体,就是说doFilter()方法就是具体的过滤处理代码,同时它可以决定被浏览器处理后下一步要进行的操作。
DoFilter的最后一个参数为FilterChain对象,对此对象调用对象的doFilter方法以激活下一个相关的过滤器。如果没有另一个过滤器与servlet或jsp页面关联,则servlet或jsp页面被激活。


destroy(),这个方法由Web容器负责调用。通常在销毁Filter对象的实例之前调用destory()方法,因为它是和init()方法相对应,所以这个方法主要用户释放init()中申请的资源。


Filter在web.xml中配置和部署
Filter的配置和部署工作是在Web应用的web.xml配置文件中进行的。在Filter的配置中应用到两个配置元素:
<filter>...</filter>
filter元素向系统注册一个过滤对象,它包含的子元素有:
filter-name用于定义Filter的名称。
Filter-class用于定义这个Filter的具体实现对象。
init-param 这是一个可选的元素,它定义可利用FilterConfig的getInitParameter方法读取的初始化参数。单个过滤器元素可包含多个init-param元素。 


<filter-mapping>...</filter-mapping>
filter-mapping元素指定该过滤对象所应用的URL。它包含的子元素有:
其中filter-name用于引用在filter元素中定义的filter名称。
url-pattern 此元素声明一个以斜杠(/)开始的模式,用于指明与URL相匹配的方式,只有相匹配的请求才会被Filter所处理。/*表示处理所有的请求,/*.jsp表示处理所有jsp页面的请求。/manage/*表示对/manage下的所有请求。如果希望过滤器适用于多个模式,可重复整个filter-mapping元素。
servlet-name 此元素给出一个名称,此名称必须与利用servlet元素给予servlet或JSP页面的名称相匹配。不能给单个filter-mapping元素提供多个servlet-name元素项。如果希望过滤器适合于多个servlet名,可重复这个filter-mapping元素。 
例如: 字符编码过滤器
<filter>
      <filter-name>SimpleFilter</filter-name>
      <filter-class>com.darkmi.filter.SimpleFilter</filter-class>
        <init-param> 
            <param-name>encoding</param-name> 
            <param-value>UTF-8</param-value> 
        </init-param> 
    </filter>
    <filter-mapping>
      <filter-name>SimpleFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>


package cn.hxex.tutorial;
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.UnavailableException;


public class SetCharacterEncodingFilter implements Filter { 
    protected String encoding = null; 
    protected FilterConfig filterConfig = null; 
    protected boolean ignore = true;


    public void destroy() { 
        this.encoding = null; 
        this.filterConfig = null; 
    }


    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
       throws IOException, ServletException { 
        // Conditionally select and set the character encoding to be used 
        if (ignore || (request.getCharacterEncoding() == null)) { 
            String encoding = selectEncoding(request); 
            if (encoding != null) 
        //设置对客户端请求进行重新编码的编码,
                request.setCharacterEncoding(encoding); 
        }


       // Pass control on to the next filter 
        chain.doFilter(request, response); 
    }


    public void init(FilterConfig filterConfig) throws ServletException { 
       this.filterConfig = filterConfig; 
        this.encoding = filterConfig.getInitParameter("encoding"); 
        String value = filterConfig.getInitParameter("ignore"); 
        if (value == null) 
            this.ignore = true; 
        else if (value.equalsIgnoreCase("true")) 
            this.ignore = true; 
        else if (value.equalsIgnoreCase("yes")) 
            this.ignore = true; 
        else 
            this.ignore = false; 
    }


    // ------------------------------------------------------ 
    //Protected Methods 
    protected String selectEncoding(ServletRequest request) { 
        return (this.encoding); 
    } 
}




使浏览器不缓存页面的过滤器:
import  javax.servlet. * ; 
import  javax.servlet.http.HttpServletResponse; 
import  java.io.IOException; 


/**  
* 用于的使 Browser 不缓存页面的过滤器 
*/  
public   class  ForceNoCacheFilter  implements  Filter  { 


public   void  doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)  throws  IOException, ServletException 

((HttpServletResponse) response).setHeader( " Cache-Control " , " no-cache " ); 
((HttpServletResponse) response).setHeader( " Pragma " , " no-cache " ); 
((HttpServletResponse) response).setDateHeader ( " Expires " ,  - 1 ); 
filterChain.doFilter(request, response); 
}  


public   void  destroy()  { 
}  


public   void  init(FilterConfig filterConfig)  throws  ServletException  { 
}  














































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值