对应设计模式的Listener模式,事件触发时会自动触发该事件对应的Listener。主要监听session、request、context等进行监听。
Listener的概述
使用Listener和Event来完成相应事件的处理。
listener的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
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); }
}
|
1 2 3 4 5
|
<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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
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。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
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接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
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使用案例
单点登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
<%@ 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>
|
原文:大专栏 读书笔记--监听器Listener