大家在登陆qq的时候,电脑上登陆了qq,如果另一台机器上也登陆该qq账号,那么之前的qq账号会被挤下去。
我们现在用web的方式来做一个非常简单的演示。
先简单的说一下功能吧,
用户只有一个User,这个entity设置成账号为hello,密码world
![](https://img-blog.csdn.net/20160821200155187?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这样做为了简化不到数据库里面去查用户的账号信息。
首先,我们看一看我们的web.xml
-
<?xml version="1.0" encoding="UTF-8"?>
-
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
-
- <listener>
- <listener-class>SessionListener</listener-class>
- </listener>
-
</web-app>
web.xml里面就配置了一个HttpSessionListener
类SessionListener的实现如下
- import javax.servlet.http.HttpSession;
- import javax.servlet.http.HttpSessionEvent;
- import javax.servlet.http.HttpSessionListener;
- import java.util.HashMap;
-
- /**
- * Created by HuLuo on 2016/8/20.
- */
- public class SessionListener implements HttpSessionListener
- {
- /**
- * 该HashMap以用户名-HttpSession对象存储一个账号只能被一个人登陆的信息。
- */
- public static HashMap<String,HttpSession> sessionMap = new HashMap<String,HttpSession>();
-
- @Override
- public void sessionCreated(HttpSessionEvent httpSessionEvent)
- {
- HttpSession session = httpSessionEvent.getSession();
- }
-
- @Override
- public void sessionDestroyed(HttpSessionEvent httpSessionEvent)
- {
-
- HttpSession session = httpSessionEvent.getSession();
-
- delSession( session );
- }
-
- public static synchronized void delSession(HttpSession session)
- {
- if(session != null)
- {
-
- // 删除单一登录中记录的变量
- if(session.getAttribute( "users" ) != null)
- {
- User user = (User) session.getAttribute( "users" );
- SessionListener.sessionMap.remove( user.getUsername() );
- }
- }
- }
-
- }
public static HashMap<String,HttpSession> sessionMap = new HashMap<String,HttpSession>();
这个HashMap是用来存储用户的登陆信息,一个账户同时只能被一个人使用。
接着是demo的首页面,里面很简单,只有一个超链接,让其访问到
${pageContext.request.contextPath}/login
这边笔者也是简化的不能再简化了,直接连账户名密码也不用填。直接登陆上。。。。。。
![](https://img-blog.csdn.net/20160821200955245?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
再来我们看LoginServlet.Java ------------------------------>判断这个账号是否被其他人登陆的逻辑判断
![](https://img-blog.csdn.net/20160821201357438?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
代码如下
-
import javax.servlet.ServletException;
-
import javax.servlet.annotation.WebServlet;
-
import javax.servlet.http.HttpServlet;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
import javax.servlet.http.HttpSession;
-
import java.io.IOException;
-
-
/**
-
* Created by HuLuo on 2016/8/20.
-
*/
-
@WebServlet(urlPatterns = "/login")
-
public class LoginServlet extends HttpServlet
- {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- {
- User user = new User();
- HttpSession session = req.getSession();
- /**
-
* 该账号已经被登陆
-
*/
- if(null != SessionListener.sessionMap.get( user.getUsername() ))
- {
- /**
-
* 将已经登陆的信息拿掉,将新的用户登录信息放进去
-
*/
- ForceLogoutUtils.forceUserLogout( user.getUsername() );
-
- SessionListener.sessionMap.put( user.getUsername(), session );
- }
- /**
-
* 该账号未被登陆
-
*/
- else
- {
- SessionListener.sessionMap.put( user.getUsername(), session );
- }
- session.setAttribute( "users", user );
- req.getRequestDispatcher( "result.jsp" ).forward( req,resp );
- }
- }
然后我们接着讲ForceLogoutUtils.java
这个类呢是用来,当发现账号已经被人登陆了,就将这个已经登陆上的人的Session从SessionListener.java中的HashMap里给拿到,并且移除在此HashMap中的记录
并将session invalidate掉。
![](https://img-blog.csdn.net/20160821201655410?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
- import javax.servlet.http.HttpSession;
- import java.util.Enumeration;
-
- /**
- * Created by HuLuo on 2016/8/20.
- */
- public class ForceLogoutUtils
- {
- public static void forceUserLogout(String username)
- {
- if(SessionListener.sessionMap.get( username ) != null)
- {
- HttpSession session = SessionListener.sessionMap.get( username );
-
- SessionListener.sessionMap.remove( username );
-
- Enumeration e = session.getAttributeNames();
-
- while(e.hasMoreElements())
- {
- String sessionName = (String) e.nextElement();
-
- session.removeAttribute( sessionName );
- }
-
- session.invalidate();
- }
- }
- }
在LoginServlet.java处理的结果出来之后,跳转到一个result.jsp这个页面
页面内容也是只有一个超链接。检查自己是否被踢下
<%-- 以下的超链接用于检验自己登陆的被踢下,被踢下了返回到index.jsp页面 --%>
<a href="${pageContext.request.contextPath}/check">检验</a>
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2016/8/20
Time: 11:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 以下的超链接用于检验自己登陆的被踢下,被踢下了返回到index.jsp页面 --%>
<a href="${pageContext.request.contextPath}/check">检验</a>
</body>
</html>
如果被踢下返回到index.jsp页面,如果没有被踢下,就继续留在result.jsp
是否被踢下
最后我们来看CheckServlet.java里面的逻辑判断
![](https://img-blog.csdn.net/20160821202955740?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
-
import javax.servlet.ServletException;
-
import javax.servlet.annotation.WebServlet;
-
import javax.servlet.http.HttpServlet;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
-
-
/**
-
* Created by HuLuo on 2016/8/20.
-
*/
-
@WebServlet(urlPatterns = "/check")
-
public class CheckServlet extends HttpServlet
- {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- {
- User user = (User) req.getSession().getAttribute( "users" );
-
- if(null == user)
- {
-
- resp.sendRedirect( "index.jsp" );
- }
- else
- {
- resp.sendRedirect( "result.jsp" );
- }
-
- }
- }
判断从Session中拿到,是否有users信息,如果有继续留在result.jsp页面,如果没有重定向到index.jsp