MyEclipse中新建Web Project项目,完整目录如下:
需要的jar包为commons-logging-xxx.jar
1、singleton.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <jsp:directive.page import="com.wang.singleton.PersonInfo"/> <% String action = request.getParameter("action"); String account = request.getParameter("account"); if("login".equals(action) && account.trim().length()>0){ PersonInfo personInfo = new PersonInfo(); personInfo.setAccount(account); 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)){ 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> </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"/><br/> <a href="${pageContext.request.requestURI}?action=logout">退出</a> <!-- 每五秒钟刷新一次页面 --> <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>
2、PersonInfo.java
package com.wang.singleton; import java.io.Serializable; import java.util.Date; public class PersonInfo implements Serializable{ private static final long serialVersionUID = 1L; private String account; private String ip; private Date loginDate; public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Date getLoginDate() { return loginDate; } public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } public boolean equals(Object obj){ if(obj == null || !(obj instanceof PersonInfo)){ return false; } return account.equalsIgnoreCase(((PersonInfo) obj).getAccount()); } }
3、LoginSessionListener.java
package com.wang.singleton; import java.util.HashMap; import java.util.Map; 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 LoginSessionListener implements HttpSessionAttributeListener { Log log= LogFactory.getLog(this.getClass()); Map<String,HttpSession> map = new HashMap<String,HttpSession>(); public LoginSessionListener() { // TODO Auto-generated constructor stub } public void attributeRemoved(HttpSessionBindingEvent event) { // 删除属性前被调用 String name = event.getName(); if(name.equals("personInfo")){ PersonInfo personInfo = (PersonInfo) event.getValue(); map.remove(personInfo.getAccount()); log.info("账号"+personInfo.getAccount()+"注销"); } } public void attributeAdded(HttpSessionBindingEvent event) { // 添加session时被调用 String name = event.getName(); if(name.equals("personInfo")){ PersonInfo personInfo = (PersonInfo) event.getValue(); if(map.get(personInfo.getAccount()) != null){ HttpSession session = map.get(personInfo.getAccount()); PersonInfo oldPersonInfo = (PersonInfo) session.getAttribute("personInfo"); log.info("账号"+oldPersonInfo.getAccount()+"在"+oldPersonInfo.getIp()+"已经登录,该登录将被迫下线!"); session.removeAttribute("personInfo"); session.setAttribute("msg", "您的账号已经在其他机器上登录,您被迫下线!"); } map.put(personInfo.getAccount(), event.getSession()); log.info("账号"+personInfo.getAccount()+"在"+personInfo.getIp()+"登录"); } } public void attributeReplaced(HttpSessionBindingEvent event) { // 修改属性时被调用 String name = event.getName(); if(name.equals("personInfo")){ PersonInfo oldPersonInfo = (PersonInfo) event.getValue(); //移除旧的登录信息 map.remove(oldPersonInfo.getAccount()); //新的登录信息 PersonInfo personInfo = (PersonInfo) event.getSession().getAttribute("personInfo"); //也要检查新的账号是否在别的机器上登录 if(map.get(personInfo.getAccount()) != null){ HttpSession session = map.get(personInfo.getAccount()); session.removeAttribute("personInfo"); session.setAttribute("msg", "您的账号已经在其他机器上登录,您被迫下线!"); } map.put(personInfo.getAccount(), event.getSession()); log.info("账号"+personInfo.getAccount()+"在"+personInfo.getIp()+"登录"); } } }
实现效果
1、在谷歌浏览器随便输入一串英文
2、显示如下
3、换个IE浏览器,输入相同一串英文,原来登录的就被挤掉了
参考:《javaweb王者归来》