Java 监听器简介
监听器是Servlet规范定义的一种特殊类,用于监听ServletContext,HttpSession,ServletRequest等域对象的创建、销毁及其属性修改发生变化的事件。监听器可以在事件发生前后进行一些必要的处理操作。
常见的应用场景
- 统计在线人数和在线用户
- 应用启动时完成信息初始化工作
- 网站访问量的统计
- 与Spring结合
- Web系统防止用户重复登陆
监听器的实现步骤
1.编写java类实现监听器接口,并实现其接口方法
2.在web.xml文件中对实现的监听器类进行注册
Java监听器按监听事件分类
- 域对象自身的创建和销毁事件监听器
- 域对象中属性的创建、替换和消除事件监听器
- 绑定到session中某个对象的状态事件监听器(不需要在web.xml中注册)
app_name
Listener Web
version
1.0
com.listener.MyServletContextListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
String appName = (String)sce.getServletContext().getAttribute("app_name");
String version = (String)sce.getServletContext().getAttribute("version");
System.out.println("MyServletContextListener destroyed,appName:" + appName + ",version:" + version);
}
@Override
public void contextInitialized(ServletContextEvent sce) {
String appName = sce.getServletContext().getInitParameter("app_name");
String version = sce.getServletContext().getInitParameter("version");
sce.getServletContext().setAttribute("app_name", appName);
sce.getServletContext().setAttribute("version", version);
System.out.println("MyServletContextListener init,appName:" + appName + ",version:" + version);
}
}
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent hse) {
String sessionId = hse.getSession().getId();
Date createTime = new Date(hse.getSession().getCreationTime());
System.out.println("session id:"+sessionId+",createTime:"+createTime);
}
@Override
public void sessionDestroyed(HttpSessionEvent hse) {
String sessionId = hse.getSession().getId();
System.out.println("session destroyed,session id:"+sessionId);
}
}
com.listener.MyHttpSessionListener
1
访问index.jsp,创建一个会话,后台输出sessionId,再用另一个浏览器访问,就会再创建一个sessionId,一分钟后销毁。
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("request listener,request destroyed... ...");
}
@Override
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 is :" + par);
}
}
com.listener.MyServletRequestListener
首页
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("ServletContext#attAdded#name:" + scae.getName() + "#value:" + scae.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("ServletContext#attRemoved#name:" + scae.getName() + "#value:" + scae.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("ServletContext#attReplaced#name:" + scae.getName() + "#value:" + scae.getValue());
}
}
com.listener.MyServletContextAttributeListener
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
application.setAttribute("servletcontextPar", "servletcontext_par");
//application.removeAttribute("servletcontextPar");
//application.setAttribute("servletcontextPar", "servletcontext_par1");
%>
attribute_add_listener_test
attribute_removed_listener_test
attribute_replaced_listener_test
public class User implements HttpSessionBindingListener {
private String username;
private String password;
@Override
public void valueBound(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
System.out.println("value bound,name:"+name);
}
@Override
public void valueUnbound(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
System.out.println("value unbound,name:"+name);
}
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;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
session.setAttribute("user", new com.model.User());
// session.removeAttribute("user");
%>
binding_listener_test
unbinding_listener_test
Java监听器项目案例
- 通过过滤器实现登录控制,未登录用户不能访问系统首页
- 用户登录,将登录名存储到session里
- 登录监听器监听session属性中登录值属性变化
- 若登录用户用户名已登录系统,清除前次登录信息
- 记录该次登录信息至缓存中,用于下次登录判断
登陆权限过滤验证
public class SessionFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest hrequest = (HttpServletRequest)request;
HttpServletResponse hresponse = (HttpServletResponse)response;
String loginUser = (String)hrequest.getSession().getAttribute("loginUser");//从session对象中获取登录用户名
if(loginUser==null){//登录用户名不存在,用户未登录,强制重定向至登陆页面
hresponse.sendRedirect(hrequest.getContextPath()+"/index.jsp?flag=1");
return;
}else{
chain.doFilter(request, response);//已登录,转入相应的请求处理
return;
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
用户信息存储实现
/** 这里用到了单例模式 **/
public class LoginCache {
private static LoginCache instance = new LoginCache();
/**servlet api 3.0版本中HttpSessionContext中的httpSession不支持直接通过sessionId获得Session对象**/
/** 因此通过用户名获取sessionId,然后通过sessionId获取session**/
private Map loginUserSession = new HashMap();// key值:登录用户登录名,value值:登录用户sessionId
private Map loginSession = new HashMap();//key值:登录用户sessionId,value值:登录用户session对象
private LoginCache(){
}
public static LoginCache getInstance(){
return instance;
}
/**
* 通过登录名获取对应登录用户的sessionId
* @param username
* @return
*/
public String getSessionIdByUsername(String username){
return loginUserSession.get(username);
}
/**
* 通过sessionId获取对应的session对象
* @param sessionId
* @return
*/
public HttpSession getSessionBySessionId(String sessionId){
return loginSession.get(sessionId);
}
/**
* 存储登录名与对应的登录sessionID至缓存对象
* @param username
* @param sessionId
*/
public void setSessionIdByUserName(String username,String sessionId){
loginUserSession.put(username, sessionId);
}
/**
* 存储sessionId与对应的session对象至缓存对象
* @param sessionId
* @param session
*/
public void setSessionBySessionId(String sessionId,HttpSession session){
loginSession.put(sessionId, session);
}
}
监听功能实现
public class LoginSessionListener implements HttpSessionAttributeListener {
private static final String LOGIN_USER="loginUser";
@Override
public void attributeAdded(HttpSessionBindingEvent hsbe) {
String attrName = hsbe.getName();//监听到session属性值发生添加操作,获取对应操作的属性名
if(LOGIN_USER.equals(attrName)){//若属性名为登录属性名,判定为用户登录操作
String attrVal = (String)hsbe.getValue();//获取添加的属性值,即用户登录名
HttpSession session = hsbe.getSession();//该次操作的session对象
String sessionId = session.getId();//该次操作的session对象ID
String sessionId2 = LoginCache.getInstance().getSessionIdByUsername(attrVal);//从缓存对象里面,获得该用户登录名对应的sessionID值
if(null == sessionId2){//未获得结果,不需要清理前次登录用户会话信息
}else{
HttpSession session2 = LoginCache.getInstance().getSessionBySessionId(sessionId2);//获取前次该用户登录对应的session对象
session2.invalidate();//清理前次登录用户会话存储信息,使得前次登录失效
}
//完成该次登录用户登录名、sessionID,session对象的缓存对象存储
LoginCache.getInstance().setSessionIdByUserName(attrVal, sessionId);
LoginCache.getInstance().setSessionBySessionId(sessionId, session);
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
}
web.xml
com.listener.LoginSessionListener
sessionFilter
com.filter.SessionFilter
sessionFilter
/main.jsp
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String flag = request.getParameter("flag");
%>
Login
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String username = request.getParameter("username");
String password = request.getParameter("password");
session.setAttribute("loginUser", username);//登录完成,将登录用户名存储至session对象
response.sendRedirect(request.getContextPath()+"/main.jsp");
%>
main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String user = (String)session.getAttribute("loginUser");
%>
Peculiar a Personal Portfolio Flat Bootstarp responsive Website Template| HOME :: w3layouts
PROIN CONVALLIS SED FELIS EU MALESUADA
Etiam in porttitor risus. Curabitur non diam id lacus facilisis consequat. Integer pulvinar ex nunc, id porttitor orci sollicitudin id. Morbi vitae sodales arcu, vel maximus neque. Nullam a faucibus justo sit.
RESUME
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000
BLOG
Random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000
OTHERS
Lorem Ipsum is not simply random text. Latin literature from 45 BC, making it over 2000 years old
Contact Me
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
T: 212-555-1211