Listener实现单态登陆

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王者归来》

原文地址:https://www.cnblogs.com/Donnnnnn/p/6230163.html