导读:监听器用来监视ServletContext/Session/Request的创建、初始化、销毁以及其中的属性变动。


监听器的分类

常见的主要有以下6个,分别处理Servlet全局、Session和Request。

  • ServletContextListener
  • ServletContextAttributeListener
  • HttpSessionListener
  • HttpSessionAttributeListener
  • ServletRequestListener
  • ServletRequestAttributeListenser

监听器的作用

由于每当一个用户访问一个网站都会产生一个会话或是一个请求,所以可以使用监听器来监视这些会话和请求,能够用于

  • 统计在线人数
  • 统计访问量
  • 应用启动时信息初始化
  • 与Spring结合

监听器的实现

根据需要实现上述的六种接口,对象监听器实现Init和Destroy方法,属性监听器实现Add/Remove/Replace方法。然后在web.xml中对监听器进行配置,相比于Servlet和Filter,监听器的配置更为简单。

ServletContextListener举例

public class MyServletContextListener implements ServletContextListener {@Overridepublic 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("Init:"+appName+"  "+version);}@Overridepublic void contextDestroyed(ServletContextEvent sce) {String appName=(String)sce.getServletContext().getAttribute("app_name");String version=(String)sce.getServletContext().getAttribute("version");System.out.println("Destroy:"+appName+"  "+version);}
}

在web.xml中进行配置,设置全局属性,用于获取。

<context-param><param-name>app_name</param-name><param-value>Listener Web</param-value>
</context-param>
<context-param><param-name>version</param-name><param-value>1.0</param-value>
</context-param><listener><listener-class>listener.MyServletContextListener</listener-class>
</listener>

这样,一旦WEB应用一启动,监听器就能够监视ServletContext对象的创建和销毁,控制台就会输出"Init:Listener 1.0",关闭WEB应用,就会输出"Destroy:Listener   1.0"。

对于SessionRequest也类似,只要一创建新的Session和Request,就会被监听器所捕获到,执行操作。

ServletContextAttributeListener举例

属性监视器用来监视属性的添加、变换和移除。新建一个全局属性监听器。

public class MyServletContextAttrListener implements ServletContextAttributeListener {@Overridepublic void attributeAdded(ServletContextAttributeEvent scae) {System.out.println(scae.getName()+scae.getValue());}@Overridepublic void attributeRemoved(ServletContextAttributeEvent scae) {System.out.println(scae.getName()+scae.getValue());}@Overridepublic void attributeReplaced(ServletContextAttributeEvent scae) {System.out.println(scae.getName()+scae.getValue());}
}

新建一个jsp,用于添加全局属性:

<%application.setAttribute("servletContextPar","servlet");
%>

访问这个jsp,由于执行了添加属性的操作,所以会在后台输出属性名和属性值。

其它属性监听器类似。


监听器实现单一登录

类似QQ这种软件,当用户在别处登录时,本地登录将会被“挤掉”,可以用监听器来实现。下面的案例,使用HttpSessionAttributeListener来实现这个功能。

登录:

index首页有一个表单,用于提交用户名和密码,然后发送请求参数到login.jsp。在login.jsp中,将传过来的用户名存放在名为loginUser的session属性中,接着重定向到主页main.jsp。

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%String username=request.getParameter("username");session.setAttribute("loginUser",username);response.sendRedirect(request.getContextPath()+"/main.jsp");
%>

main.jsp中,需要获取重定向过来的username,并在页面上显示:

<%String user = (String)session.getAttribute("loginUser");
%><ul class="navig"><li><a href="index.html" class="scroll"><%=user  %></a><span>|</span></li><li><a href="index.html" class="scroll">HOME</a><span>|</span></li><li><a href="#portfolio" class="scroll">PORTFOLIO</a><span>|</span></li><li><a href="#contact" class="scroll">CONTACT</a></li>
</ul>

过滤器拦截:

如果用户未经登录,就想访问main.jsp,会被拒绝,重新定向到登录页面,并附带一条错误信息,这就需要创建一个Filter来处理。

public class SessionFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest hrequest=(HttpServletRequest)request;HttpServletResponse hresponse=(HttpServletResponse)response;//获取session中的loginUserString loginUser=(String)hrequest.getSession().getAttribute("loginUser");if(loginUser==null){//如果为空,则表示用户没有登录,返回到index.jsp并附带消息hresponse.sendRedirect(hrequest.getContextPath()+"/index.jsp?flag=1");}else{chain.doFilter(request,response);}}
}

在index.jsp登录页面中,先获取过滤器传过来的flag参数,再显示警告。

<%String flag=request.getParameter("flag");
%><script type="text/javascript">var flag='<%=flag%>'if(flag=="1"){alert("尚未登录或在异地登录,请重新登录!")}
</script>

单例类构建:

由于只允许一个用户登录,需要一个单例类来封装这个用户。这个单例类用来映射用户名-SessionId,SessionId-Session的关系。由于3.0以上的Servlet不能由sessionId获取到session,所以需要直接写一个由sessionId获取session的方法。

还有一点,为什么不直接使用用户名去映射session,而是要通过sessionId来中转一下。这是因为同一个浏览器的同一个用户,如果退出了浏览器,此时session还在,当这个用户再访问网站时,会建立一个新的session,释放旧的session,浪费资源。如果通过用户名-sessionId,得知当前浏览器当前用户又一次登录了,直接用这个用户名之前的sessionId获取之前的session就行了,避免了资源浪费。

public class LoginCache {//单例类要点private static LoginCache instance=new LoginCache();private LoginCache(){}public static LoginCache getInstance(){ return instance; }//用户名跟sessionId映射private Map<String,String>loginUserSession=new HashMap<>();//sessionId和session的映射private Map<String, HttpSession>loginSession=new HashMap<>();public String getSessionIdByUsername(String username){return loginUserSession.get(username);}public HttpSession getSessionBySessionId(String sessionId){return loginSession.get(sessionId);}public void setSessionIdByUserName(String username,String sessionId){loginUserSession.put(username,sessionId);}public void setSessionBySessionId(String sessionId,HttpSession session){loginSession.put(sessionId,session);}
}

监听器构建:

public class LoginSessionListener implements HttpSessionAttributeListener {private static final String LOGIN_USER="loginUser";@Overridepublic void attributeAdded(HttpSessionBindingEvent hsbe) {//获取新添加的属性名String attrName=hsbe.getName();//如果=loginUser,就表示有新用户登录了if(LOGIN_USER.equals(attrName)){//获得新登录的用户名String attrVal=(String)hsbe.getValue();//获得当前会话(新登录)的Session对象HttpSession session=hsbe.getSession();//获得SessionIdString sessionId=session.getId();//在LoginCache中查找新登录的用户名是否存在String sessionId2=LoginCache.getInstance().getSessionIdByUsername(attrVal);if(sessionId2==null){}//如果存在else{//就获取之前用户的SessionId2,并将其释放HttpSession session2=LoginCache.getInstance().getSessionBySessionId(sessionId2);session2.invalidate();}//添加刚才登录的Session作为已存在的SessionLoginCache.getInstance().setSessionIdByUserName(attrVal,sessionId);LoginCache.getInstance().setSessionBySessionId(sessionId,session);}}
}

这样,当从别的浏览器登录时,刷新当前浏览器,就会被挤掉。

【JavaWeb】用监听器实现单一登录相关推荐

  1. JavaWeb中监听器Listener+过滤器filter+拦截器interceptor区别

    JavaWeb中监听器Listener+过滤器filter+拦截器interceptor区别 如果从整个项目中看,一个servlet请求的执行过程就变成了这样context-param–>lis ...

  2. java拦截到登陆界面,JavaWeb 使用Filter实现自动登录

    JavaWeb 使用Filter实现自动登录 思路 使用cookie存储账号.密码,使用Filter拦截,从cookie中取出账号.密码.若用户要注销|登出.不再想使用自动登录,将cookie的有效期 ...

  3. openid saml2_单一登录云:SAML和OpenId

    openid saml2 当访问不同组织拥有的不同应用程序时,每次从一个应用程序转到另一个应用程序时都必须进行身份验证. 这不仅耗时,而且您还必须记住多个经常丢失的密码. 单一登录是一次认证的能力,并 ...

  4. 单一登录云:SAML和OpenId

    当访问不同组织拥有的不同应用程序时,每次从一个应用程序转到另一个应用程序时都必须进行身份验证. 不仅浪费时间,而且您还必须记住多个经常丢失的密码. 单一登录是一次认证的能力,并且能够使用已认证的身份在 ...

  5. java单终端登陆_配置终端服务单一登录

    配置终端服务单一登录 配置终端服务单一登录 单一登录是一种身份验证方法,允许具有域帐户的用户使用密码或智能卡登录一次,然后,不再要求其提供凭据即可访问远程服务器. 若要在终端服务中实现单一登录功能,请 ...

  6. asp.net单一登录

    asp.net 使用 Application 限制单一登录 原理:用户登录后系统会分配一个与用户唯一对应的SessionID,将当前用户ID与其SessionID对应保存在Application中,一 ...

  7. java单一登录_java实现单一登录 踢人效果

    1.建一个session监听类 public class SessionListener implements HttpSessionListener{ public static HashMap s ...

  8. java实现单一登录 踢人效果

    1.建一个session监听类 public class SessionListener implements HttpSessionListener{public static HashMap se ...

  9. Javaweb 实现简单的用户注册登录(含数据库访问功能)

    Javaweb 实现简单的用户注册登录(含数据库访问功能) 实现效果图: 登录界面: 登陆成功: 登陆失败: 注册界面: 注册成功: 1.登录界面login.jsp <%@ page langu ...

  10. ibm tivoli_Windows和Tivoli Access Manager的Intranet单一登录

    ibm tivoli 基于Microsoft Windows的Intranet提供了使用桌面凭据登录基于Microsoft Internet信息服务的Intranet基础结构的能力. 这是使用Micr ...

最新文章

  1. 如何完整迁移git仓库到另一个远程地址
  2. 《JavaScript 闯关记》之函数
  3. 今天网络又出问题了,现在的问题变成原IP地址不可用
  4. 【翻译】C#编程语言和JAVA编程语言的比较(下)
  5. 【MFC系列-第11天】CWinApp类成员分析
  6. LeetCode 2063. 所有子字符串中的元音(数学)
  7. phpcmsV9 会员升级 - 配置篇
  8. FPGA入门基础介绍
  9. 以新型数据治理构筑城市发展新引擎,中国电子和清华大学联合发布 《2021中国城市数据治理工程白皮书》
  10. Python让繁琐工作自动化——chapter16 发送电子邮件和短信
  11. 田汉卿:量化投资与风险控制(会议纪要)
  12. 网管教程+从入门到精通软件篇
  13. 在项目中遇到导入TXT乱码现象。为什么UTF-8不行?ANSI是什么编码?
  14. Android 使用 Scheme 启动淘宝,天猫等其他APP
  15. 这台iPad最适合程序媛吃鸡,号称吃鸡神器!
  16. life: zz 关于爱情
  17. zabbix_get [12429]: Check access restrictions in Zabbix agent configuration
  18. 家庭教育机构如何线上线下灵活结合?
  19. oppo计算机怎么添加到桌面,OPPO怎么把快捷方式添加到桌面 OPPO把快捷方式添加到桌面方法...
  20. 主动降噪相消干涉原理

热门文章

  1. java 变位词,变位词 java
  2. c++实现植物大战僵尸修改器
  3. 数学知识学习之——商空间(Quotient Spaces)
  4. 计算机系毕业论文指导老师评语,设计指导教师的评语
  5. Cisco路由器VLan隔离局域网广播包的配置实验
  6. IDEA修改快捷键方法(在原快捷键不变的基础上增加自己习惯的快捷键)
  7. 计算机二级mysql数据库试题,计算机二级mysql数据库模拟试题及答案.docx
  8. 【Java实验】文件中单词重复字母对的查找
  9. Eclipse在桌面上创建的快捷方式打不开
  10. Python实现穷举破解WiFi密码