//登录页面 login.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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">
<script type="text/javascript" src="./js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="./js/vue.js"></script>
<title>登录</title>
<%
String msg = (String)(request.getAttribute("msg")==null?"":request.getAttribute("msg"));
%>
<script type="text/javascript">
function show(){
if('<%=msg%>'!=''){
alert('<%=msg%>');
}
}
</script>
</head>
<body style="text-align: center" οnlοad="show();">
<form action="${pageContext.request.contextPath}/login.do" method="post">
<table border="1">
<tr>
<td align="center" colspan="2">
<h3>用户登录</h3>
</td>
</tr>
<tr>
<td align="right">
用户名
</td>
<td align="left">
<input type="text" id="userName" name="userName">
</td>
</tr>
<tr>
<td align="right">
密 码
</td>
<td align="left">
<input type="password" id="password" name="password">
</td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" value="登录"> <input type="reset" value="重置">
</td>
</tr>
</table>
</form>
</body>
</html>

  //主页面 main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>登录成功</title>
<script type="text/javascript" src="./js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="./js/vue.js"></script>
</head>
<%
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","No-cache");
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "No-store");
String userName = "";
userName = (String)(session.getAttribute("userName")==null?"":session.getAttribute("userName"));
%>
<script type="text/javascript">
var count;
var userMsg = '';
var i =0;
function checkUserOnline(){
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/checkUserOnline.do",
dataType : "text",
success:function(data){
userMsg = data;
//alert(JSON.stringify(userMsg))
},
error:function(){
alert("获取用户信息失败!");
clearInterval(count);
reLogin();
}
});
if(userMsg=='null'||userMsg==''|| userMsg == 'undefined'){
return;
}else{
//alert(JSON.stringify(userMsg));
clearInterval(count);
reLogin();
}
}
function reLogin(){
window.location = "login.jsp";
} function checkLogin(){
alert("检查");
count = setInterval("checkUserOnline()",5000);
}
</script>
<body onclick="checkLogin()">
<%
if(!"".equals(userName)){
out.print("登陆成功!<br/>用户名:<span id='userName'>"+userName+"</span><br/><input type='button' value='重新登陆' οnclick='reLogin();'/>");
}
%>
</body>
</html>

  //控制类 LoginController

package com.zjn.oneLogin.dengLu;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; @Controller
public class LoginController{
/**
* 用户和Session绑定关系
*/
public static final Map<String, HttpSession> USER_SESSION = new HashMap<String, HttpSession>();
/**
* seeionId和用户的绑定关系
*/
public static final Map<String, String> SESSIONID_USER = new HashMap<String, String>();
@RequestMapping("/login")
@ResponseBody
public Map<String,Object>toLogin(HttpServletRequest request, HttpServletResponse response) throws Exception{
//获取请求命令
request.setCharacterEncoding("utf-8");
String servletPath = request.getServletPath();//获取请求路径
String uri = servletPath.substring(1, servletPath.lastIndexOf(".do")); try{
//登录
if ("login".equals(uri)){
HttpSession session = request.getSession();
String userName = request.getParameter("userName");
String password = request.getParameter("password"); if (userName != null && !"".equals(userName.trim())){
//登录成功
if (login(userName, password)){
//处理用户登录(保持同一时间同一账号只能在一处登录)
userLoginHandle(request); //添加用户与HttpSession的绑定
USER_SESSION.put(userName.trim(), session);
//添加sessionId和用户的绑定
SESSIONID_USER.put(session.getId(), userName);
System.out.println("添加sessionId和用户的绑定 ==="+session.getId());
System.out.println("用户[" + userName + "] 已上线...");
session.setAttribute("userName", userName);
session.removeAttribute("userMsg");//从session中移除用户信息
//重定向到首页
response.sendRedirect("main.jsp"); }
//登录失败
else{
System.out.println("用户[" + userName + "] 登录失败...");
request.setAttribute("msg", "登录失败,请重新登录!");
//response.sendRedirect("login.jsp");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
else{
System.out.println("用户[" + userName + "] 登录失败..."); request.setAttribute("msg", "登录失败,请重新登录!"); //response.sendRedirect("login.jsp");
request.getRequestDispatcher("login.jsp").forward(request, response);//跳转到用户页面,返回请求响应对象
}
}else if ("reLogin".equals(uri)){
//重新登陆
HttpSession session = request.getSession();
String userName = (String)session.getAttribute("userName");
if (session != null){
//销毁相关session
//USER_SESSION.remove(SESSIONID_USER.remove(session.getId()));
session.invalidate();
}
if (userName != null && !"".equals(userName)){
System.out.println("用户[" + userName + "] 已下线...");
}
//重定向到登录页面
response.sendRedirect("login.jsp");
} }
catch (Exception e){
System.out.println(e.getClass() + e.getMessage());
PrintWriter out = response.getWriter();
out.print("服务器内部错误!");
}
return null; } /**
*
* Description:用户登录时的处理 <br>
* @param request
* @see
*/
private void userLoginHandle(HttpServletRequest request){
//当前登录的用户
String userName = request.getParameter("userName");
System.out.println("userName=="+userName);
//当前sessionId
//String sessionId = request.getSession().getId(); //删除当前sessionId绑定的用户,用户--HttpSession
//USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
//删除当前登录用户已绑定的HttpSession
HttpSession session = USER_SESSION.remove(userName);//map中的remove方法返回删除value值 if (session != null){
//删除已登录的sessionId绑定的用户
SESSIONID_USER.remove(session.getId());
session.removeAttribute("userName");
session.setAttribute("userMsg", "您的账号已经在另一处登录,您被迫下线!");
}
} /**
*
* Description: 模拟DB登录判断<br>
* @param userName 用户
* @param password 密码
* @return
* @see
*/
private boolean login(String userName, String password){
return ("peizhongxian".equals(userName) && "123456".equals(password));
} /**
* 判断用户是否同时登陆同一个用户
*
* */
@RequestMapping(value="/checkUserOnline")
@ResponseBody
public void checkUserOnline(HttpServletRequest request,HttpServletResponse response) throws IOException{
HttpSession session=request.getSession();
PrintWriter out = response.getWriter();
out.print(session.getAttribute("userMsg"));
} }

  //监听器 MyListener

package com.zjn.oneLogin.dengLu;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; public class MyListener implements HttpSessionListener { /**
* 实现HttpSessionListener接口监听 监听session的创建事件
*/
public void sessionCreated(HttpSessionEvent se){
String sessionId = se.getSession().getId();
System.out.println("创建session sessionId= " + sessionId);
} /**
* 实现HttpSessionListener接口监听 监听session的销毁事件
*/
public void sessionDestroyed(HttpSessionEvent se){
String sessionId = se.getSession().getId();
System.out.println("sessionId========="+sessionId);
//当前session销毁时删除当前session绑定的用户信息
//同时删除当前session绑定用户的HttpSession
LoginController.USER_SESSION.remove(LoginController.SESSIONID_USER.remove(sessionId)); System.out.println("销毁session sessionId= " + sessionId);
} }

  //web.xml 文件

 <listener>
<listener-class>com.zjn.oneLogin.dengLu.MyListener</listener-class>
</listener>

  

java保持同一时间同一账号只能在一处登录的更多相关文章

  1. SpringMVC实现账号只能在一处登陆

    一.问题引导 在Web开发中,实现一个账号只能在一处登陆有两种形式:1.当某个账号在某处登陆后,如果再在其他处登陆,将前一个账号挤掉:2.当某个账号登陆后,此账号在其他设备登陆提示已经登陆,无法登陆. ...

  2. asp.net mvc 简单实现一个账号只能在一个地方登录

    原理:  假设用户在机器A登陆后,  这时用户再次在机器B登陆,会以当前会话的SessionID作为键,用户id作为值,插入dictionary集合中,集合再保存在application(保存在服务器 ...

  3. shiro实现账号同一时间只能在一处登录(非单点登录)

    <bean id="myRealm" class="com.sys.shiro.MyRealm" /> <bean id="sess ...

  4. [Java]Java日期及时间库插件 -- Joda Time.

    来到新公司工作也有一个多月了, 陆陆续续做了一些简单的项目. 今天做一个新东西的时候发现了 Joda Time的这个东西, 因为以前用的都是JDK原生的时间处理API, 大家都知道Java原生的时间处 ...

  5. Java中日期时间API小结

    Java中为处理日期和时间提供了大量的API,确实有把一件简单的事情搞复杂的嫌疑,各种类:Date Time Timestamp Calendar...,但是如果能够看到时间处理的本质就可以轻松hol ...

  6. php 实现同一个账号同时只能一个人登录

    php 实现同一个账号同时只能一个人登录 张映 发表于 2015-01-22 分类目录: php 标签:mysql, nginx, openfire, php, redis 以前考虑过这个问题,今天实 ...

  7. (Java)微信之个人公众账号开发(二)——接收并处理用户消息(下)

    接下来,我们再讲一下图文消息: 如图: 大家可以先从开发者文档中了解一下图文消息的一些参数: 如上图,用户回复4时,ipastor返回了几条图文消息,上图中属于多图文消息,当然还有单图文消息,图文消息 ...

  8. Java 8 日期时间API

    Java 8一个新增的重要特性就是引入了新的时间和日期API,它们被包含在java.time包中.借助新的时间和日期API可以以更简洁的方法处理时间和日期; 在介绍本篇文章内容之前,我们先来讨论Jav ...

  9. java学习第13天( java获取当前时间,有关大数据的运算及精确数字运算,Date类)

    一 java获取当前时间 学习一个函数,得到当前时间的准确值 System.currectTimeMillis(). 可以得到以毫秒为单位的当前时间.它主要用于计算程序运行时间,long start= ...

随机推荐

  1. Spring事务传播级别

    项目中用的默认值: 具体的,转载:https://segmentfault.com/a/1190000013341344 注: DataSourceTransactionManager只支持单数据源

  2. dubbo 远程调用

    记得服务暴露的时候createServer()里 server = Exchangers.bind(url, requestHandler); requestHandler在DubboProtocol ...

  3. 2014.04.28基于CPLD的LCOS场序彩色视频控制器设计

    基于CPLD的LCOS场序彩色视频控制器设计 作者:宋丹娜,代永平,刘艳艳,商广辉 发表刊物:液晶与显示,2009 学习时间:2014.04.28 文章讲述了-- (和上一篇论文有些相似之处) 1. ...

  4. 06_Intent和IntentFilter

    Intent是同一个或不同的应用中的组件之间的消息传递的媒介,是一个将要执行动作的抽象描述,一般来说是作为参数来使用. Intent描述要启动的基本组件: IntentFilter对组件进行过滤. 下 ...

  5. C++ 虚基类的定义、功能、规定

    原文声明:http://blog.sina.com.cn/s/blog_93b45b0f01011pkz.html 虚继承和虚基类的定义是非常的简单的,同时也是非常容易判断一个继承是否是虚继承的,虽然 ...

  6. 第7章 Python类型、类、协议 第7.1节 面向对象程序设计的相关知识

    Python被视为一种面向对象的语言,在介绍Python类相关的内容前,本节对面向对象程序设计相关的概念进行简单介绍. 一.    类和对象(实例) 在面向对象的程序设计(OOP)过程中有两个重要概念 ...

  7. 转:【Python3网络爬虫开发实战】 requests基本用法

    1. 准备工作 在开始之前,请确保已经正确安装好了requests库.如果没有安装,可以参考1.2.1节安装. 2. 实例引入 urllib库中的urlopen()方法实际上是以GET方式请求网页,而 ...

  8. 第二十二章、 Model/View便利类树型部件QTreeWidget

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 树部件(Tree Widget)是Qt Designer中 Item Widgets(It ...

  9. 第14.12节 Python中使用BeautifulSoup解析http报文:使用select方法快速定位内容

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>和<第14.11节 Python中使用BeautifulSo ...

  10. 静湖ABC段扫描器(长更)

    想学习python图形化的知识,从C段扫描器开始入手,很多的扫描器只能扫描C段,对于A,B段却没有设置这个功能,所以想将扫描A段和B段的功能跟C段一起做了. 暂时的想法是,先完成C段扫描器,扫描的同时 ...