监听器
- web应用服务器通过监听器来监听servlet和与之对应的jsp中的三个内置对象。
- web监听器本身是servlet规范定义的一种特殊类
- 用于监听ServletContext、HttpSession、ServletRequest等域对象的创建、销毁、及其属性修改变化发生的事件
- 监听器可以在事件发生前后进行一些必要的处理操作
常见应用场景
- 统计在线人数
- 页面访问量统计
- 应用启动时完成信息初始化工作
- 与spring结合
监听器实现步骤
1、编写Java类实现监听器接口,并实现其接口方法。
2、在web.xml文件中对实现的监听器类进行注册。
监听器按监听事件分类
- 域对象自身的创建和销毁事件监听器
- 域对象中属性的创建、替换和消除事件监听器
- 绑定到session中的某个对象的状态事件监听器
ServletContextListener
- 案例
servlet3.0可以不必在web.xml中配置 程序中有注解@WebListener
package com.alan.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextListener implements ServletContextListener {
public MyServletContextListener() {
}
public void contextDestroyed(ServletContextEvent sce) {
//在ServletContext对象中获取域中的值
String appName = (String) sce.getServletContext().getAttribute("app_name");
String version = (String) sce.getServletContext().getAttribute("version");
//打印输出
System.out.println("appName="+appName);
System.out.println("version="+version);
}
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
//从web.xml获得初始化参数
String appName = sce.getServletContext().getInitParameter("app_name");
String version = sce.getServletContext().getInitParameter("version");
//将参数赋值到ServletContext作用域中
sce.getServletContext().setAttribute("app_name", appName);
sce.getServletContext().setAttribute("version", version);
//打印输出
System.out.println("appName="+appName);
System.out.println("version="+version);
}
}
ListenerDemoWebProj
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
app_name
Listener Web
version
1.0
com.alan.listener.MyServletContextListener
SessionListener
- 每一个浏览器就会创建一个session
- MyServletContextListener
package com.alan.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextListener implements ServletContextListener {
public MyServletContextListener() {
}
public void contextDestroyed(ServletContextEvent sce) {
//在ServletContext对象中获取域中的值
String appName = (String) sce.getServletContext().getAttribute("app_name");
String version = (String) sce.getServletContext().getAttribute("version");
//打印输出
System.out.println("appName="+appName);
System.out.println("version="+version);
}
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
//从web.xml获得初始化参数
String appName = sce.getServletContext().getInitParameter("app_name");
String version = sce.getServletContext().getInitParameter("version");
//将参数赋值到ServletContext作用域中
sce.getServletContext().setAttribute("app_name", appName);
sce.getServletContext().setAttribute("version", version);
//打印输出
System.out.println("appName="+appName);
System.out.println("version="+version);
}
}
- web.xml
1
-
效果图
ServletRequestListener
package com.alan.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
public MyServletRequestListener() {
// TODO Auto-generated constructor stub
}
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("request listener destroyed...");
}
public void requestInitialized(ServletRequestEvent sre) {
//向下转型
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
//获得请求路径和请求参数
String path = request.getRequestURI();
String par = request.getParameter("par");
System.out.println("request listener path:"+path+",par:"+par);
}
}
ServletContextAttributeListener
package com.alan.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
public MyServletContextAttributeListener() {
// TODO Auto-generated constructor stub
}
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("attributeAdded name:"+scae.getName()+",value:"+scae.getValue());
}
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("attributeRemoved name:"+scae.getName()+",value:"+scae.getValue());
}
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("attributeReplaced name:"+scae.getName()+",value:"+scae.getValue());
}
}
HttpSessionBindingListener
- 不需要在web.xml中注册,即可使用
package com.alan.model;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
//@WebListener
public class User implements HttpSessionBindingListener {
private String username ;
private String passowrd;
public User() {
// TODO Auto-generated constructor stub
}
public void valueBound(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
System.out.println("valueBound name:"+name);
}
public void valueUnbound(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
System.out.println("valueUnbound name:"+name);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassowrd() {
return passowrd;
}
public void setPassowrd(String passowrd) {
this.passowrd = passowrd;
}
}
实际案例
实现登陆用户不能重复登陆的功能
1、实现登陆功能
2、登陆权限过滤器验证
3、用户信息存储实现
4、监听功能实现
项目存放在 LoginListenerWebProj
- 监听核心代码
package com.alan.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import com.alan.cache.LoginCache;
@WebListener
public class LoginSessionListener implements HttpSessionAttributeListener {
//定义常量方便操作
private static final String LOGIN_USER = "loginUser";
public LoginSessionListener() {
}
public void attributeAdded(HttpSessionBindingEvent hsbe) {
String attrName = hsbe.getName();
//session中有可能有很多的定义的属性,需要判断是否为需要的loginUser
if(LOGIN_USER.equals(attrName)) {
//获取属性值、session、sessionId.
String value = (String)hsbe.getValue();
HttpSession session = hsbe.getSession();
String sessionId = session.getId();
//获取缓存中的sessionId判断是否登陆过
String sessionIdInCache = LoginCache.getLoginCache().getSessionIdByLoginName(value);
//如果sessionInCache为空,说明当前用户没有登陆过
if(sessionIdInCache==null) {
LoginCache.getLoginCache().setSessionIdByLoginName(value, sessionId);
LoginCache.getLoginCache().setSessionBySessionId(sessionId, session);
}else {
//已经存在的话,取到原来的session将其销毁
HttpSession sessionInCache = LoginCache.getLoginCache().getSessionBySessionId(sessionIdInCache);
sessionInCache.invalidate();
//将新的session覆盖到map集合中
LoginCache.getLoginCache().setSessionIdByLoginName(value, sessionId);
LoginCache.getLoginCache().setSessionBySessionId(sessionId, session);
}
}
}
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
}
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
}
}
- 单例模式cache创建
package com.alan.cache;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
public class LoginCache {
//单例模式实现
//创建用户名与sessionId的键值对
private Map loginUserSession = new HashMap<>();
//创建sessionId与session对象的键值对
private Map loginSession = new HashMap<>();
//1、构造函数私有化
private LoginCache() {
}
//2、将对象私有静态实例化
private static LoginCache instance = new LoginCache();
//3、通过公有静态方法返回该对象
public static LoginCache getLoginCache() {
return instance;
}
//方法:根据用户名返回对应的sessionId
public String getSessionIdByLoginName(String LoginName) {
return loginUserSession.get(LoginName);
}
//方法:根据sessionId返回对应的session对象
public HttpSession getSessionBySessionId(String sessionId) {
return loginSession.get(sessionId);
}
//方法:将用户名和sessionId存入map集合中
public void setSessionIdByLoginName(String loginName,String sessionId) {
loginUserSession.put(loginName, sessionId);
}
//方法:将sessionId和session对象存入map集合中
public void setSessionBySessionId(String sessionId,HttpSession session ) {
loginSession.put(sessionId, session);
}
}