Listener
1、功能
2、listener模型
常见的监听接口
3、【跟生命周期有关的监听器】
public void contextInitialized( ServletContextEvent event )
»当 容器 加载 ( deploy ) 一个 应用 ( "web application" ) 时 呼叫 contextInitialized
»传入的事件对象是 ServletContextEvent
public void contextDestroyed( ServletContextEvent event )
»当 容器 卸载 ( undeploy ) 一个 应用 ( "web application" ) 时 呼叫 contextDestroyed
»传入的事件对象是 ServletContextEvent
测试案例:
package ecut.listener.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ApplicationLifecycleListener implements ServletContextListener {
public ApplicationLifecycleListener() {
//System.out.println( "WebApplicationLifecycleListener" );
}
public void contextInitialized( ServletContextEvent sce ) {
ServletContext application = sce.getServletContext();
String name = application.getServletContextName();
String contextPath = application.getContextPath();
System.out.println( "正在加载: " + name + " , 它相应的路径为: " + contextPath );
}
public void contextDestroyed( ServletContextEvent sce ) {
ServletContext application = sce.getServletContext();
String name = application.getServletContextName();
System.out.println( "正在卸载: " + name + " 。");
}
}
listener
ecut.listener.listener.ApplicationLifecycleListener
运行结果如下:
正在加载: listener , 它相应的路径为: /s
......................
正在卸载: listener 。
......................
正在卸载: listener 。
public void sessionCreated( HttpSessionEvent event )
»当 创建 会话 对象时,呼叫 sessionCreated
public void sessionDestroyed( HttpSessionEvent event )
»当 销毁 会话 对象时,呼叫 sessionDestroyed
»销毁 会话对象的时机 : session 的 有效期 到了 、调用 session.invalidate()
»可以在 web.xml 中配置 session 的有效期:
注意,这里的有效期的时间的单位是 分钟
测试案例:
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet( "/session/show" )
public class ShowSessionIdServlet extends HttpServlet {
private static final long serialVersionUID = 3683961647674453725L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
HttpSession session = request.getSession();
// 通过代码来设置 会话的有效期 ( 时间单位是 秒 )
session.setMaxInactiveInterval( 30 ); // 最长发呆时间 ( 从客户端最后一次访问 session 开始持续30秒 )
response.setContentType( "text/html" );
response.getWriter().println( "" + session.getId() + "
" );
}
}
package ecut.listener.listener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionLifecycleListener implements HttpSessionListener {
@Override
public void sessionCreated( HttpSessionEvent event ) {
HttpSession session = event.getSession();
System.out.println( "会话[ " + session.getId() + " ]创建成功" );
}
@Override
public void sessionDestroyed( HttpSessionEvent event ) {
HttpSession session = event.getSession();
System.out.println( "准备销毁[ " + session.getId() + " ]会话" );
}
}
ecut.listener.listener.SessionLifecycleListener
运行结果如下:
会话[ D2920D969A73184E4A173615758A314C ]创建成功
准备销毁[ D2920D969A73184E4A173615758A314C ]会话
public void requestInitialized(ServletRequestEvent event)
»当 客户端 发起请求时,即创建 请求对象 ,此时 呼叫 requestInitialized
public void requestDestroyed(ServletRequestEvent event)
»当请求 结束时 ( 响应数据已经全部返回到客户端 ) ,呼叫 requestDestroyed
测试案例:
package ecut.listener.listener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
public class RequestLifecycleListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent event) {
ServletRequest req = event.getServletRequest();
HttpServletRequest request = (HttpServletRequest) req ;
String uri = request.getRequestURI();
DispatcherType type = request.getDispatcherType();
String name = req.getLocalName();
System.out.println( "来自"+name+"请求类型为"+type + " ,请求路径是 " + uri +"的请求结束");
}
@Override
public void requestInitialized(ServletRequestEvent event) {
ServletRequest req = event.getServletRequest();
HttpServletRequest request = (HttpServletRequest) req ;
String uri = request.getRequestURI();
DispatcherType type = request.getDispatcherType();
String name = req.getLocalName();
System.out.println( "接收到请求:来自" +name+"的请求,请求类型为"+type + " ,请求路径是 " + uri );
}
}
ecut.listener.listener.RequestLifecycleListener
运行结果如下:
接收到请求:来自0:0:0:0:0:0:0:1的请求,请求类型为REQUEST ,请求路径是 /s/pages/listener/index.jsp
来自0:0:0:0:0:0:0:1请求类型为REQUEST ,请求路径是 /s/pages/listener/index.jsp的请求结束
4、【跟 属性 操作 有关的监听器】
void attributeAdded( ServletContextAttributeEvent event )
»向 ServletContext 中添加一个不存在的 属性时 呼叫 attributeAdded
ServletContext application = request.getServletContext();
application.setAttribute( "counter" , 0 ) ; // 假设 application 中 根本就没有 counter ,这是首次添加 counter
void attributeReplaced( ServletContextAttributeEvent event )
»当 ServletContext 中已经包含 某个名称的属性时,又通过 setAttribute 来设置 设个属性值,则构成 替换操作,此时呼叫 attributeReplaced
ServletContext application = request.getServletContext();
application.setAttribute( "counter" , 1 ) ; // 替换某个属性的值时,呼叫 attributeReplaced
void attributeRemoved( ServletContextAttributeEvent event )
»当从 ServletContext 移除 某个名称的 属性时 呼叫 attributeRemoved
测试案例:
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page contentType="text/html; charset=UTF-8" %>
Listener
Application
Session:
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet( "/application/add" )
public class ApplicationAddServlet extends HttpServlet {
private static final long serialVersionUID = -1218970600318038715L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
String name = request.getParameter( "name" );
String value = request.getParameter( "value" );
ServletContext application = this.getServletContext();
application.setAttribute( name , value ); // ----> ApplicationAttributeListener # attributeAdded
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet( "/application/remove" )
public class ApplicationRemoveServlet extends HttpServlet {
private static final long serialVersionUID = -6802388429975749293L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
String name = request.getParameter( "name" );
ServletContext application = this.getServletContext();
application.removeAttribute( name ); // ----> ApplicationAttributeListener # attributeRemoved
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
package ecut.listener.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class ApplicationAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded( ServletContextAttributeEvent event ) {
ServletContext application = event.getServletContext();
String name = event.getName() ;
Object value = event.getValue() ;
System.out.print( "向 " + application.getContextPath() + " 的 ServletContext 中添加属性: " );
System.out.println( name + " ,取值: " + value );
}
@Override
public void attributeReplaced( ServletContextAttributeEvent event ) {
ServletContext application = event.getServletContext();
String name = event.getName() ;
Object value = event.getValue() ; // 原来的值
System.out.print( application.getContextPath() + " 的 ServletContext 中的属性: " );
System.out.print( name );
System.out.print( " 的取值从 [ ");
System.out.print( value );
System.out.println( " ] 替换成 [ " + application.getAttribute( name ) +" ]" );
}
@Override
public void attributeRemoved( ServletContextAttributeEvent event ) {
ServletContext application = event.getServletContext();
String name = event.getName() ;
Object value = event.getValue() ;
System.out.print( "从 " + application.getContextPath() + " 的 ServletContext 中移除属性: " );
System.out.println( name + " ,取值: " + value );
}
}
运行结果如下:
向 /s 的 ServletContext 中添加属性: 女朋友 ,取值: 罗玉凤
/s 的 ServletContext 中的属性: 女朋友 的取值从 [ 罗玉凤 ] 替换成 [ 芙蓉 ]
从 /s 的 ServletContext 中移除属性: 女朋友 ,取值: 芙蓉
void attributeAdded( HttpSessionBindingEvent event )
void attributeReplaced( HttpSessionBindingEvent event )
void attributeRemoved( HttpSessionBindingEvent event )
测试案例:
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet( "/session/add" )
public class SessionAddServlet extends HttpServlet {
private static final long serialVersionUID = 7547888494941329407L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
String name = request.getParameter( "name" );
String value = request.getParameter( "value" );
HttpSession session = request.getSession();
session.setAttribute( name , value ); // ----> SesssionAttributeListener # attributeAdded
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet( "/session/remove" )
public class SessionRemoveServlet extends HttpServlet {
private static final long serialVersionUID = -6802388429975749293L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
String name = request.getParameter( "name" );
HttpSession session = request.getSession();
session.removeAttribute( name ); // ----> SesssionAttributeListener# attributeRemoved
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
package ecut.listener.listener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class SessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
String name = event.getName() ;
Object value = event.getValue() ;
System.out.print( "向 会话[" + session.getId() + " ]中添加属性: " );
System.out.println( name + " ,取值: " + value );
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
String name = event.getName() ;
Object value = event.getValue() ;
System.out.print( "从会话[ " + session.getId() + "] 中移除属性: " );
System.out.println( name + " ,取值: " + value );
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
String name = event.getName() ;
Object value = event.getValue() ; // 原来的值
System.out.print("会话[" + session.getId() + "] 中的属性: " );
System.out.print( name );
System.out.print( " 的取值从 [ ");
System.out.print( value );
System.out.println( " ] 替换成 [ " + session.getAttribute( name ) +" ]" );
}
}
运行结果如下:
向 会话[E962FCF5380CE7E04CF599D20438F25 ]中添加属性: 男朋友 ,取值: 吴彦祖
会话[E962FC9F5380CE7E04CF599D20438F25] 中的属性: 男朋友 的取值从 [ 吴彦祖 ] 替换成 [ 彭于晏 ]
从会话[ E962FC9F5380CE7E04CF599D20438F25] 中移除属性: 男朋友 ,取值: 彭于晏
void attributeAdded( ServletRequestAttributeEvent srae )
void attributeReplaced( ServletRequestAttributeEvent srae )
void attributeRemoved(ServletRequestAttributeEvent srae)
5、【 跟 Session 钝化 和 锐化 有关的监听器 】
void sessionWillPassivate( HttpSessionEvent event )
»Passivate ( 钝化 )
当 有客户端 关联的 Session 存在,并且 Session 中有数据时,如果此时 重新加载 当前Web应用,
将导致 Session 中的数据被丢失,为了保存这部分数据,容器 可能会将 Session 对象中的数据 保存到 磁盘 、网络 等存储设备中,这种行为 称作 Session 的 钝化
void sessionDidActivate( HttpSessionEvent event )
»Activate ( 锐化 )
从 硬盘或其它存储设备上的文件中重新读回 Session 数据,重新加载到 JVM 所管理的 内存中 的动作
6、【跟 属性值 绑定到 Session 有关的监听器】
void valueBound( HttpSessionBindingEvent event )
»如果该实例加入session 对象的属性,则呼叫valueBound()
void valueUnbound( HttpSessionBindingEvent event )
»假设 将要 添加到 session 中的 属性值 的类型是 Customer 类型
»如果该实例从session 对象种移除,则呼叫valueUnbound()
Customer c = new Customer();
session.setAttribute( "customer" , c ) ; // 将 Customer 类型的 对象 绑定到 session 的属性值中
session.removeAttribute( "customer" ) ; // 解除 Customer 类型的 对象 跟 session 的绑定
为了监听 Customer 对象 跟 session 是否 发生关系,则需要 将 Customer 本身 做成是 监听器
这个监听器无需在xml中或者是在类中使用注解注册Listener
统计用户在线人数测试案例:
package ecut.listener.entity;
import java.io.Serializable;
import java.util.Date;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Customer implements Serializable , HttpSessionBindingListener {
private static final long serialVersionUID = 7499870485797565944L;
private Integer id ;
private String username ;
private String password ;
private String nickname ;
private char gender ;
private Date birthdate ;
@Override
public void valueBound( HttpSessionBindingEvent event ) {
System.out.println( "绑定到 [ " + event.getSession().getId() + " ]" );
ServletContext application = event.getSession().getServletContext();
// 1、先尝试从 ServletContext 获取名称是 loginCounter 的属性
Integer loginCounter = (Integer)application.getAttribute( "loginCounter" );
// 2、判断 loginCounter 是否不存在
if( loginCounter == null ){
loginCounter = Integer.valueOf( 0 ) ;
}
// 3、将 loginCounter 增加 1 以后 再 放入到 ServletContext 中
application.setAttribute( "loginCounter" , ++loginCounter );
}
@Override
public void valueUnbound( HttpSessionBindingEvent event ) {
System.out.println( "从 [ " + event.getSession().getId() + " ] 解除绑定" );
ServletContext application = event.getSession().getServletContext();
// 1、先尝试从 ServletContext 获取名称是 loginCounter 的属性
Integer loginCounter = (Integer)application.getAttribute( "loginCounter" );
// 2、判断 loginCounter 是否不存在
if( loginCounter == null ){
application.setAttribute( "loginCounter" , 0 );
} else {
// 3、将 loginCounter 减去 1 以后 再 放入到 ServletContext 中
--loginCounter;
loginCounter = loginCounter < 0 ? 0 : loginCounter ;
application.setAttribute( "loginCounter" , loginCounter );
}
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
}
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import ecut.listener.entity.Customer;
@WebServlet( "/customer/login" )
public class CustomerLoginServlet extends HttpServlet {
private static final long serialVersionUID = 2694859066336538343L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
String username = request.getParameter( "username" );
String password = request.getParameter( "password" );
Customer c = new Customer();
c.setUsername( username );
c.setPassword( password );
HttpSession session = request.getSession() ;
session.setAttribute( "customer" , c ); // ---> Customer # valueBound
response.sendRedirect( request.getContextPath() + "/customer/main" );
return ;
}
}
package ecut.listener.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet( "/customer/logout" )
public class CustomerLogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1376263177132417940L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
HttpSession session = request.getSession();
session.removeAttribute( "customer" ); // ---> Customer # valueUnbound
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
package ecut.listener.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import ecut.listener.entity.Customer;
@WebServlet( "/customer/main" )
public class CustomerMainServlet extends HttpServlet {
private static final long serialVersionUID = 154588398950897364L;
@Override
protected void service( HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
response.setContentType( "text/html" );
PrintWriter w = response.getWriter();
ServletContext application = this.getServletContext() ;
HttpSession session = request.getSession();
Object o = session.getAttribute( "customer" );
if( o instanceof Customer ){
Customer c = (Customer) o ;
w.println( "欢迎" + c.getUsername() + " 登录
" );
w.println( "当前登陆人数:" + application.getAttribute( "loginCounter" ) + "
" );
w.println( "注销");
} else {
response.sendRedirect( request.getContextPath() + "/pages/listener/index.jsp" );
}
}
}
运行结果如下:
绑定到 [ E962FC9F5380CE7E04CF599D20438F25 ]
向 /s 的 ServletContext 中添加属性: loginCounter ,取值: 1
向 会话[E962FC9F5380CE7E04CF599D20438F25 ]中添加属性: customer ,取值: ecut.listener.entity.Customer@5be15f9f
绑定到 [ 2E6EF661378654D7120122FCDEEA1F88 ]
/s 的 ServletContext 中的属性: loginCounter 的取值从 [ 1 ] 替换成 [ 2 ]
向 会话[2E6EF661378654D7120122FCDEEA1F88 ]中添加属性: customer ,取值: ecut.listener.entity.Customer@2098d9
从 [ 2E6EF661378654D7120122FCDEEA1F88 ] 解除绑定
/s 的 ServletContext 中的属性: loginCounter 的取值从 [ 2 ] 替换成 [ 1 ]
从会话[ 2E6EF661378654D7120122FCDEEA1F88] 中移除属性: customer ,取值: ecut.listener.entity.Customer@2098d9
7、注册监听器
可以在web.xml 中添加相应的配置
»配置文件中,一般把Listener 的配置放在servlet 和filter 之前
Servlet 3.0 可以在监听器类中使用@WebListener 注解
»这个注解用于标注这个类是一个监听器,并注册给容器
»@WebListener 只有一个属性value,它是String 类型,指定当前Listener的描述
转载请于明显处标明出处
http://www.cnblogs.com/AmyZheng/p/9032454.html