使用Listener不需要关注该类事件是怎样触发的或者怎么调用相应的Listener,只要记住该类事件触发时一定会调用相应地Listener。遵循Servlet规范的服务器完成了相应地工作,开发者只要早Listener里编写相关的代码就行了。
Listener分类:
1,监听对象的创建与销毁
HttpSessionListener、ServletContextListener、ServletRequestListener分别用于监控session、context、request的创建与销毁。
以session为例:
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
// 获得新建的session
HttpSession session = se.getSession();
//打印sessionId
System.out.println(session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 打印销毁sessionId
System.out.println(se.getSession().getId());
}
}
在web.xml中注册:
<listener>
<listener-class>
com.inspur.filter.replaceText.SessionListener
</listener-class>
</listener>
2,监听对象的属性变化
这类Listener用于监听Session、context、request的属性变化,接口分别为HttpSessionAttributeListener、ServletContextAttributeListener、ServletRequestAttributeListener。当向被监听对象中添加、更新、移除属性时,会分别执行xxxAdded()、xxxReplaced()、xxxRemoved()方法。
public class SessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
//打印session新添加的属性名和属性值
System.out.println(se.getName()+se.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
//打印session移除的属性名和属性值
System.out.println(se.getName()+se.getValue());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("修改前的属性名和属性值:" + se.getName()+se.getValue());
System.out.println("修改后的属性名和属性值:" + se.getName()+se.getSession().getAttribute(se.getName()));
}
}
在web.xml中注册:
<listener>
<listener-class>
com.inspur.filter.replaceText.SessionAttributeListener
</listener-class>
</listener>
3,监听Session内的对象(这个一般用的比较少,不再举例)
这类Listener用于监控Session内的对象,分别是HttpSessionBindingListener与HttpActivationListener。
- HttpSessionBindingListener:当对象被放到Session里执行valueBound(HttpSessionBindingEvent event)方法。当对象被从Session里移除时执行valueUnbound(HttpSessionBindingEvent event)方法。
- HttpActivationListener:服务器关闭时,会将Session里的内容保存到硬盘上,这个过程叫做钝化,此时会执行sessionWillPassivate(HttpSessionEvent se)方法。服务器重新启动时,会将Session内容从硬盘上重新加载,此时会执行sessionDidACTIVATE(HttpSessionEvent se)方法。
踢人小案列
列出所有的在线用户,后台管理者拥有踢人的权利,点击踢人的超链接,该用户就被注销了。
分析
首先,怎么能列出所有的在线用户呢??一般我们在线用户都是用Session来标记的,所有的在线用户就应该用一个容器来装载所有的Session。。
我们监听Session的是否有属性添加(监听Session的属性有添加、修改、删除三个方法。如果监听到Session添加了,那么这个肯定是个在线用户!)。
装载Session的容器应该是在Context里边的【属于全站点】,并且容器应该使用Map集合【待会还要通过用户的名字来把用户踢了】
思路:
- 写监听器,监听是否有属性添加在Session里边了。
- 写简单的登陆页面。
- 列出所有的在线用户
- 实现踢人功能(也就是摧毁Session)
代码
- 监听器
public class KickPerson implements HttpSessionAttributeListener {
// Public constructor is required by servlet spec
public KickPerson() {
}
public void attributeAdded(HttpSessionBindingEvent sbe) {
//得到context对象,看看context对象是否有容器装载Session
ServletContext context = sbe.getSession().getServletContext();
//如果没有,就创建一个呗
Map map = (Map) context.getAttribute("map");
if (map == null) {
map = new HashMap();
context.setAttribute("map", map);
}
//---------------------------------------------------------------------------------------
//得到Session属性的值
Object o = sbe.getValue();
//判断属性的内容是否是User对象
if (o instanceof User) {
User user = (User) o;
map.put(user.getUsername(), sbe.getSession());
}
}
public void attributeRemoved(HttpSessionBindingEvent sbe) {
/* This method is called when an attribute
is removed from a session.
*/
}
public void attributeReplaced(HttpSessionBindingEvent sbe) {
/* This method is invoked when an attibute
is replaced in a session.
*/
}
}
- 登陆页面
<form action="${pageContext.request.contextPath }/LoginServlet" method="post">
用户名:<input type="text" name="username">
<input type="submit" value="登陆">
</form>
- 处理登陆Servlet
//得到传递过来的数据
String username = request.getParameter("username");
User user = new User();
user.setUsername(username);
//标记该用户登陆了!
request.getSession().setAttribute("user", user);
//提供界面,告诉用户登陆是否成功
request.setAttribute("message", "恭喜你,登陆成功了!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
- 列出在线用户
<c:forEach items="${map}" var="me">
${me.key} <a href="${pageContext.request.contextPath}/KickPersonServlet?username=${me.key}">踢了他吧</a>
<br>
</c:forEach>
- 处理踢人的Servlet
String username = request.getParameter("username");
//得到装载所有的Session的容器
Map map = (Map) this.getServletContext().getAttribute("map");
//通过名字得到Session
HttpSession httpSession = (HttpSession) map.get(username);
httpSession.invalidate();
map.remove(username);
//摧毁完Session后,返回列出在线用户页面
request.getRequestDispatcher("/listUser.jsp").forward(request, response);