使用监听器完成单态登录

单态登录是什么?

你可以这个样子理解吧,比如你再你的手机上登录了 你的王者荣耀账号,然后又换另一部手机进行登录,这样,你之前登录的就会被顶掉。

做单态登录,本人使用的是Me,你需要用的Jar包是commons-loggin.jar,版本随便一个都可以

来来来,先看一看有啥

,来来来,上代码,先是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.openlab.listener.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>  
         
            <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>

然后是

package com.openlab.listener;

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 LoginListener implements HttpSessionAttributeListener {  
  
   Log log= LogFactory.getLog(this.getClass());  
     
   Map<String,HttpSession> map = new HashMap<String,HttpSession>();  
    public LoginListener() {  
        // 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()+"登录");  
              
        }  
    }  
      
}  

 

package com.openlab.listener;

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());  
    }  
}  

 

运行跳转页面的时候要是出现

$%7BpageContext.request.requestURI%7D    这种情况

这是因为你的web-app的版本过低,你只需要把web.xml里面的version="2.5"改成  2.5以上的就好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过监听器实现用户单态登录,以下是实现的步骤: 1. 在web.xml中配置Session监听器,监听Session的创建和销毁事件。 ```xml <listener> <listener-class>com.example.UserSessionListener</listener-class> </listener> ``` 2. 创建一个ServletContextListener,在ServletContext初始化时创建一个保存用户信息的Map。 ```java public class UserServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { ServletContext context = sce.getServletContext(); Map<String, HttpSession> users = new HashMap<String, HttpSession>(); context.setAttribute("users", users); } public void contextDestroyed(ServletContextEvent sce) { // do nothing } } ``` 3. 创建一个Session监听器,在Session创建时将用户信息保存到ServletContext中的Map中,在Session销毁时将用户信息从Map中删除。 ```java public class UserSessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { // do nothing } public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); ServletContext context = session.getServletContext(); Map<String, HttpSession> users = (Map<String, HttpSession>) context.getAttribute("users"); users.remove((String) session.getAttribute("user")); } } ``` 4. 在登录时,先检查用户是否已经在其他机器上登录,如果已经登录,则先注销原来的登录。然后将用户信息保存到Session中,并将用户信息保存到ServletContext的Map中。 ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); ServletContext context = session.getServletContext(); Map<String, HttpSession> users = (Map<String, HttpSession>) context.getAttribute("users"); String user = request.getParameter("user"); String sessionId = session.getId(); // check if user has already logged in from another machine HttpSession oldSession = users.get(user); if (oldSession != null) { oldSession.invalidate(); } session.setAttribute("user", user); users.put(user, session); // rest of the login logic } ``` 5. 在注销时,将用户信息从Session中删除,并将用户信息从ServletContext的Map中删除。 ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); ServletContext context = session.getServletContext(); Map<String, HttpSession> users = (Map<String, HttpSession>) context.getAttribute("users"); String user = (String) session.getAttribute("user"); session.removeAttribute("user"); users.remove(user); // rest of the logout logic } ``` 这样,就可以实现用户单态登录了。当用户在其他机器上登录时,原来的登录会自动失效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值