Java Servlet实现同一账号后登陆挤掉前一个登陆(类似QQ)

实现类似QQ登陆功能,账号已在一处登陆,在另外一处登陆时,将挤掉前一次的登录。

 

原理简介:

 

主要是servlet中对用户登录时的处理,servlet中维护了用户和sessionId的关系以及用户和session的关系,保存在两个map中,当用户登录时会向map中新增一条记录,如果

发现map中已经有了该用户,则将该用户对应的记录删掉,注意是将map中的记录删掉而不是将session销毁,然后在该session中放入给用户提示的信息,再将新用户的信息

放入map中。在页面中需要不断的验证session中有没有提示信息,如果有则说明已经被挤掉,有一点要注意的是,jsp中获取到的session中的attribute是不会自动更新的,也

就是说如果不刷新页面,即使servlet已经向该用户的session中放入了提示信息,页面中也不会得到的,所以这里我们需要用Ajax的方式不断的向服务器发送请求以获取

session中用户提示信息的动态,一旦发现session中有提示信息,就给出提示。

 

 

项目结构:

             

 

web.xml

             

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

  3. <display-name>LoginPush</display-name>

  4.  
  5. <listener>

  6. <listener-class>cn.com.hafx.LoginServlet</listener-class>

  7. </listener>

  8.  
  9. <servlet>

  10. <servlet-name>login</servlet-name>

  11. <servlet-class>cn.com.hafx.LoginServlet</servlet-class>

  12. </servlet>

  13. <servlet-mapping>

  14. <servlet-name>login</servlet-name>

  15. <url-pattern>/login.do</url-pattern>

  16. <url-pattern>/reLogin.do</url-pattern>

  17. <url-pattern>/getUserMsg.do</url-pattern>

  18. </servlet-mapping>

  19.  
  20. <welcome-file-list>

  21. <welcome-file>login.jsp</welcome-file>

  22. </welcome-file-list>

  23.  
  24. </web-app>

 

LoginServlet.java

 

 
  1. import java.io.IOException;

  2. import java.io.PrintWriter;

  3. import java.util.HashMap;

  4. import java.util.Map;

  5.  
  6. import javax.servlet.ServletException;

  7. import javax.servlet.http.HttpServlet;

  8. import javax.servlet.http.HttpServletRequest;

  9. import javax.servlet.http.HttpServletResponse;

  10. import javax.servlet.http.HttpSession;

  11. import javax.servlet.http.HttpSessionEvent;

  12. import javax.servlet.http.HttpSessionListener;

  13.  
  14. import org.apache.commons.logging.Log;

  15. import org.apache.commons.logging.LogFactory;

  16.  
  17.  
  18. /**

  19. *

  20. * @author lyh

  21. * @version 2013-4-11

  22. * @see LoginServlet

  23. * @since

  24. */

  25. public class LoginServlet extends HttpServlet implements HttpSessionListener

  26. {

  27. /**

  28. * 序列号

  29. */

  30. private static final long serialVersionUID = -2080934157550504694L;

  31.  
  32. /**

  33. * 日志

  34. */

  35. private static Log log = LogFactory.getLog(LoginServlet.class);

  36.  
  37. /**

  38. * 用户和Session绑定关系

  39. */

  40. public static final Map<String, HttpSession> USER_SESSION = new HashMap<String, HttpSession>();

  41.  
  42. /**

  43. * seeionId和用户的绑定关系

  44. */

  45. public static final Map<String, String> SESSIONID_USER = new HashMap<String, String>();

  46.  
  47. /**

  48. * 实现HttpSessionListener接口监听 监听session的创建事件

  49. */

  50. @Override

  51. public void sessionCreated(HttpSessionEvent se)

  52. {

  53. String sessionId = se.getSession().getId();

  54.  
  55. log.info("创建session sessionId= " + sessionId);

  56. }

  57.  
  58. /**

  59. * 实现HttpSessionListener接口监听 监听session的销毁事件

  60. */

  61. @Override

  62. public void sessionDestroyed(HttpSessionEvent se)

  63. {

  64. String sessionId = se.getSession().getId();

  65.  
  66. //当前session销毁时删除当前session绑定的用户信息

  67. //同时删除当前session绑定用户的HttpSession

  68. USER_SESSION.remove(SESSIONID_USER.remove(sessionId));

  69.  
  70. log.info("销毁session sessionId= " + sessionId);

  71. }

  72.  
  73. /**

  74. * 用户登录

  75. */

  76. @Override

  77. protected void service(HttpServletRequest request, HttpServletResponse response)

  78. throws ServletException, IOException

  79. {

  80.  
  81. //获取请求命令

  82. request.setCharacterEncoding("utf-8");

  83. String servletPath = request.getServletPath();

  84. String uri = servletPath.substring(1, servletPath.lastIndexOf(".do"));

  85.  
  86. try

  87. {

  88. //登录

  89. if ("login".equals(uri))

  90. {

  91. HttpSession session = request.getSession();

  92. String userName = request.getParameter("userName");

  93. String password = request.getParameter("password");

  94.  
  95. if (userName != null && !"".equals(userName.trim()))

  96. {

  97. //登录成功

  98. if (login(userName, password))

  99. {

  100. //处理用户登录(保持同一时间同一账号只能在一处登录)

  101. userLoginHandle(request);

  102.  
  103. //添加用户与HttpSession的绑定

  104. USER_SESSION.put(userName.trim(), session);

  105.  
  106. //添加sessionId和用户的绑定

  107. SESSIONID_USER.put(session.getId(), userName);

  108.  
  109. log.info("用户[" + userName + "] 已上线...");

  110.  
  111. session.setAttribute("userName", userName);

  112. session.removeAttribute("userMsg");

  113.  
  114. //重定向到首页

  115. response.sendRedirect("main.jsp");

  116. }

  117. //登录失败

  118. else

  119. {

  120. log.info("用户[" + userName + "] 登录失败...");

  121.  
  122. request.setAttribute("msg", "登录失败,请重新登录!");

  123.  
  124. //response.sendRedirect("login.jsp");

  125. request.getRequestDispatcher("login.jsp").forward(request, response);

  126. }

  127. }

  128. else

  129. {

  130. log.info("用户[" + userName + "] 登录失败...");

  131.  
  132. request.setAttribute("msg", "登录失败,请重新登录!");

  133.  
  134. //response.sendRedirect("login.jsp");

  135. request.getRequestDispatcher("login.jsp").forward(request, response);

  136. }

  137. }

  138. //重新登陆

  139. else if ("reLogin".equals(uri))

  140. {

  141. HttpSession session = request.getSession();

  142. String userName = (String)session.getAttribute("userName");

  143. if (session != null)

  144. {

  145. //销毁相关session

  146. //USER_SESSION.remove(SESSIONID_USER.remove(session.getId()));

  147. session.invalidate();

  148. }

  149. if (userName != null && !"".equals(userName))

  150. {

  151. log.info("用户[" + userName + "] 已下线...");

  152. }

  153. //重定向到登录页面

  154. response.sendRedirect("login.jsp");

  155. }

  156. //ajax校验

  157. else if ("getUserMsg".equals(uri))

  158. {

  159. HttpSession session = request.getSession();

  160.  
  161. response.setContentType("text/html");

  162. response.setCharacterEncoding("utf-8");

  163.  
  164. PrintWriter out = response.getWriter();

  165. out.print(session.getAttribute("userMsg"));

  166. }

  167. }

  168. catch (Exception e)

  169. {

  170. log.error(e.getClass() + e.getMessage());

  171. PrintWriter out = response.getWriter();

  172. out.print("服务器内部错误!");

  173. }

  174. }

  175.  
  176. /**

  177. *

  178. * Description:用户登录时的处理 <br>

  179. * @param request

  180. * @see

  181. */

  182. private void userLoginHandle(HttpServletRequest request)

  183. {

  184. //当前登录的用户

  185. String userName = request.getParameter("userName");

  186.  
  187. //当前sessionId

  188. //String sessionId = request.getSession().getId();

  189.  
  190. //删除当前sessionId绑定的用户,用户--HttpSession

  191. //USER_SESSION.remove(SESSIONID_USER.remove(sessionId));

  192.  
  193. //删除当前登录用户已绑定的HttpSession

  194. HttpSession session = USER_SESSION.remove(userName);

  195. if (session != null)

  196. {

  197. //删除已登录的sessionId绑定的用户

  198. SESSIONID_USER.remove(session.getId());

  199.  
  200. session.removeAttribute("userName");

  201. session.setAttribute("userMsg", "您的账号已经在另一处登录,您被迫下线!");

  202. }

  203. }

  204.  
  205. /**

  206. *

  207. * Description: 模拟DB登录判断<br>

  208. * @param userName 用户

  209. * @param password 密码

  210. * @return

  211. * @see

  212. */

  213. private boolean login(String userName, String password)

  214. {

  215. return ("lyh".equals(userName) && "123456".equals(password));

  216. }

  217.  
  218. }


login.jsp

 

 
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  4. <html>

  5. <head>

  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  7. <title>登录</title>

  8. <%

  9. String msg = (String)(request.getAttribute("msg")==null?"":request.getAttribute("msg"));

  10. %>

  11. <script type="text/javascript">

  12. function show(){

  13. if('<%=msg%>'!=''){

  14. alert('<%=msg%>');

  15. }

  16. }

  17. </script>

  18. </head>

  19. <body style="text-align: center" onload="show();">

  20. <form action="login.do" method="post">

  21. <table border="1">

  22. <tr>

  23. <td align="center" colspan="2">

  24. <h3>用户登录</h3>

  25. </td>

  26. </tr>

  27. <tr>

  28. <td align="right">

  29. 用户名

  30. </td>

  31. <td align="left">

  32. <input type="text" id="userName" name="userName">

  33. </td>

  34. </tr>

  35. <tr>

  36. <td align="right">

  37. 密 码

  38. </td>

  39. <td align="left">

  40. <input type="password" id="password" name="password">

  41. </td>

  42. </tr>

  43. <tr>

  44. <td align="center" colspan="2">

  45. <input type="submit" value="登录">

  46.  

  47. <input type="reset" value="重置">

  48. </td>

  49. </tr>

  50. </table>

  51. </form>

  52. </body>

  53. </html>


 

main.jsp

 

 
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  4. <html>

  5. <head>

  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  7. <title>登录成功</title>

  8. <script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>

  9. </head>

  10. <%

  11. response.setHeader("Pragma","No-cache");

  12. response.setHeader("Cache-Control","No-cache");

  13. response.setDateHeader("Expires", -1);

  14. response.setHeader("Cache-Control", "No-store");

  15. String userName = "";

  16. userName = (String)(session.getAttribute("userName")==null?"":session.getAttribute("userName"));

  17. %>

  18. <script type="text/javascript">

  19. var int;

  20. var userMsg = '';

  21. var i =0;

  22. function checkUserOnline(){

  23. $.ajax({

  24. type:"post",

  25. url:"getUserMsg.do",

  26. dataType : "text",

  27. success:function(data){userMsg = data;},

  28. error:function(){

  29. alert("获取用户信息失败!");

  30. clearInterval(int);

  31. reLogin();

  32. }

  33. });

  34. if(userMsg=='null'||userMsg==''){

  35. return;

  36. }

  37. else{

  38. alert(userMsg);

  39. clearInterval(int);

  40. reLogin();

  41. }

  42. }

  43. function reLogin(){

  44. window.location = "reLogin.do";

  45. }

  46.  
  47. function checkLogin(){

  48. int = setInterval("checkUserOnline()",500);

  49. }

  50. </script>

  51. <body onload="checkLogin()">

  52. <%

  53. if(!"".equals(userName)){

  54. out.print("登陆成功!<br/>用户名:<span id='userName'>"+userName+"</span><br/><input type='button' value='重新登陆' onclick='reLogin();'/>");

  55. }

  56. %>

  57. </body>

  58. </html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值