对应设计模式的Listener模式,事件触发时会自动触发该事件对应的Listener。主要监听session、request、context等进行监听。
Listener的概述
使用Listener和Event来完成相应事件的处理。
listener的使用
1234567891011121314151617 | import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;public class SessionListenerTest implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("新创建了一个session: " + session); } public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("销毁了一个session: " + session); }} |
12345 | <listener> <listener-class> com.helloweenvsfei.listener.SessionListenerTest </listener-class></listener> |
Listener的分类
8中listener,主要监听session、request、context的创建和销毁。6中Event
监听对象的创建和销毁
HttpSessionListener、ServletContextListener、ServletRequestListener分别用于监听Session、content、request的创建和销毁。
HttpSessionListener:创建Session时:sessionCreated(HttpSessionEvent se);超时或者执行session.invalidate()时: sessionDestroyed(HttpSessionEvent se)。用于收集在线信息。
ServletContextListener:服务启动或者热部署时:contextInitialized(ServletContextEvent event);服务器关闭或者只关闭web时:contextDestroyed(ServletContextEvent event)。该listener可用获取web.xml里面的配置的初始化信息。
ServletRequestListener:用户请求时:requestInitialized(ServletRequestEvent event);请求完成自动销毁时:requestDestroyed(ServletRequestEvent event)。如果html页面有多个图片会多次触发listener事件。
实例:监听session、request、context
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 | import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;public class ListenerTest implements HttpSessionListener, ServletContextListener, ServletRequestListener { Log log = LogFactory.getLog(getClass()); // 创建 session public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); log.info("新创建一个session, ID为: " + session.getId()); } // 销毁 session public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); log.info("销毁一个session, ID为: " + session.getId()); } // 加载 context public void contextInitialized(ServletContextEvent sce) { ServletContext servletContext = sce.getServletContext(); log.info("即将启动" + servletContext.getContextPath()); } // 卸载 context public void contextDestroyed(ServletContextEvent sce) { ServletContext servletContext = sce.getServletContext(); log.info("即将关闭" + servletContext.getContextPath()); } // 创建 request public void requestInitialized(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest) sre .getServletRequest(); String uri = request.getRequestURI(); uri = request.getQueryString() == null ? uri : (uri + "?" + request .getQueryString()); request.setAttribute("dateCreated", System.currentTimeMillis()); log.info("IP " + request.getRemoteAddr() + " 请求 " + uri); } // 销毁 request public void requestDestroyed(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest) sre .getServletRequest(); long time = System.currentTimeMillis() - (Long) request.getAttribute("dateCreated"); log.info(request.getRemoteAddr() + "请求处理结束, 用时" + time + "毫秒. "); }} |
监听对象的属性变化
另一个Listener用于监听Session、context、request的属性变化,借口名格式为:xxxAttributeListener,包括HttpSessionAttributeListener、ServletContextAttributeListener、ServletRequestAttributeListener。当当向被监听对象添加、更新、移除属性时,会分别执行xxxAdded()/xxxReplaced()/xxxRemoved()方法,xxx分别代表Session、context、request。
1234567891011121314151617181920212223242526272829303132333435 import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;public class SessionAttributeListenerTest implements HttpSessionAttributeListener { Log log = LogFactory.getLog(getClass()); // 添加属性 public void attributeAdded(HttpSessionBindingEvent se) { HttpSession session = se.getSession(); String name = se.getName(); log.info("新建session属性:" + name + ", 值为:" + se.getValue()); } // 删除属性 public void attributeRemoved(HttpSessionBindingEvent se) { HttpSession session = se.getSession(); String name = se.getName(); log.info("删除session属性:" + name + ", 值为:" + se.getValue()); } // 修改属性 public void attributeReplaced(HttpSessionBindingEvent se) { HttpSession session = se.getSession(); String name = se.getName(); Object oldValue = se.getValue(); log.info("修改session属性:" + name + ", 原值:" + oldValue + ", 新值:" + session.getAttribute(name)); }}
监听Session内的对象
HttpSessionBindingListener:当对象放到Session里面执行:valueBound(HttpSessionBindingEvent event);当对象从Session中移除时执行:valueUnbound(HttpSessionBindingEvent event)。对象必须实现Listener接口。
HttpSessionActivationListener:服务器关闭时会将Session里的内容保存到硬盘上,这个过程叫做钝化。服务器重新启动时会将Session内容从硬盘上重新加载。当Session里的内容被钝化时执行:sessionWillPassivate(HttpSessionEvent se);当对象重新加载时:sessionDidActivte(HttpSessionEvent se)。对象必须实现Listener接口。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 | import java.io.Serializable;import java.util.Date;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionActivationListener;import javax.servlet.http.HttpSessionBindingEvent;import javax.servlet.http.HttpSessionBindingListener;import javax.servlet.http.HttpSessionEvent;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;public class PersonInfo implements HttpSessionActivationListener, HttpSessionBindingListener, Serializable { private static final long serialVersionUID = -4780592776386225973L; Log log = LogFactory.getLog(getClass()); private String name; private Date dateCreated; public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDateCreated() { return dateCreated; } public void setDateCreated(Date dateCreated) { this.dateCreated = dateCreated; } // 从硬盘加载后 public void sessionDidActivate(HttpSessionEvent se) { HttpSession session = se.getSession(); log.info(this + "已经成功从硬盘中加载。sessionId: " + session.getId()); } // 即将被钝化到硬盘时 public void sessionWillPassivate(HttpSessionEvent se) { HttpSession session = se.getSession(); log.info(this + "即将保存到硬盘。sessionId: " + session.getId()); } // 被放进session前 public void valueBound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); String name = event.getName(); log.info(this + "被绑定到session "" + session.getId() + ""的" + name + "属性上"); // 记录放到session中的时间 this.setDateCreated(new Date()); } // 从session中移除后 public void valueUnbound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); String name = event.getName(); log.info(this + "被从session "" + session.getId() + ""的" + name + "属性上移除"); } @Override public String toString() { return "PersonInfo(" + name + ")"; }} |
Listener使用案例
单点登录
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 | <%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %><jsp:directive.page import="com.helloweenvsfei.singleton.PersonInfo" /><% String action = request.getParameter("action"); String account = request.getParameter("account"); if("login".equals(action) && account.trim().length() > 0){ // 登录,将personInfo放入session PersonInfo personInfo = new PersonInfo(); personInfo.setAccount(account.trim().toLowerCase()); personInfo.setIp(request.getRemoteAddr()); personInfo.setLoginDate(new java.util.Date()); session.setAttribute("personInfo", personInfo); response.sendRedirect(response.encodeRedirectURL(request.getRequestURI())); return; } else if("logout".equals(action)){ // 注销,将personInfo从session中移除 session.removeAttribute("personInfo"); response.sendRedirect(response.encodeRedirectURL(request.getRequestURI())); return; }%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <style type="text/css"> body { font-size:12px; } </style> </head> <body> <c:choose> <c:when test="${ personInfo != null }"> <!-- 已经登录,将显示帐号信息 --> 欢迎您,${ personInfo.account }。<br/> 您的登录IP为${ personInfo.ip },<br/> 登录时间为<fmt:formatDate value="${ personInfo.loginDate }" pattern="yyyy-MM-dd HH:mm"/>。 <a href="${ pageContext.request.requestURI }?action=logout">退出</a> <!-- 每5秒钟刷新一次页面 --> <script>setTimeout("location=location; ", 5000); </script> </c:when> <c:otherwise> <!-- 没有登录,将显示登录页面 --> ${ msg } <c:remove var="msg" scope="session" /> <form action="${ pageContext.request.requestURI }?action=login" method="post"> 帐号: <input name="account" /> <input type="submit" value="登录"> </form> </c:otherwise> </c:choose> </body></html> |