关于Session,在Java Web开发中,为我们提供了很多方便,Session是由浏览器和服务器之间维护的。好吧,闲话不多说,下面让我们一步一步来实现它们。

(一)首先来说下Session超时时间设置的三种方式,这些相对来说比较简单:

(1)在web.xml中设置session-config


<session-config>
<session-timeout>2</session-timeout>
</session-config>

即交互间隔时间最长为2分钟(该处时间单位为分钟),2分钟后session.getAttribute()获取的值为空。

(2)在Tomcat的/conf/web.xml中session-config,默认值为:30分钟


<session-config>
<session-timeout>30</session-timeout>
</session-config>

同上,时间单位为分钟。

(3)在Servlet中设置


HttpSession session = request.getSession();
session.setMaxInactiveInterval(60);

即在你的程序代码中手动设置(该处时间单位为秒)。

优先级:Servlet中设置 >web.xml设置 > Tomcat/conf/web.xml设置

(二)同一用户强制下线

大家都知道在目前很多的web项目中,大多数情况下都是可以让同一个用户账号在不同的登录入口登录的,但这样其实就显得不是很严谨了,毕竟信息修改等操作对于信息是否能完全即时同步还是个未知之数。所以,接下来,我要做的只是对于不同浏览器的同一个用户账号的强制下线处理,对于同一个浏览器暂不做考虑,先来看下面这张图。大概的了解一下:

从上面可以看出:同一个浏览器对于不同的账号,登录时会产生相同的sessionId,这也就导致了用户之间信息的覆盖;不同浏览器对于不同的账号登录时,登录时会产生不同的sessionId,这也就给了我们可操作的空间了,正是要利用这一点来进行判断和相应处理。

(1)添加监听器

为了方便这里使用Session监控的方式,创建SessionListener,如下:


public class SessionListener implements HttpSessionBindingListener{ @Override
public void valueBound(HttpSessionBindingEvent event){
// TODO Auto-generated method stub }
@Override
public void valueUnbound(HttpSessionBindingEvent event){
// TODO Auto-generated method stub }
}

这里HttpSessionBindingListener和HttpSessionListener效果一样,大家可以任选其一。重载两个方法:session的创建和销毁。

当然,在web.xml中添加相应配置是必不可少的:


<listener>
<listener-class>com.yoki.util.SessionListener</listener-class>
</listener>

由于sessionId和userId需要存储,方便后面的判断,我们在上面的类中添加两个Map,如下:


//保存username和session的映射
public static HashMap<String,Session> MAP1 = new HashMap<String,Session>();
//保存sessionID和username的映射
public static HashMap MAP2 = new HashMap();

最后,用户登录验证成功时需要调用一个方法来判断是否强制下线:


public static void userLogin(Session session,String sUserName){
//已登录
if(MAP2.containsValue(sUserName)){
Session l_session = MAP1.get(sUserName);
//不同浏览器,同一用户(强制下线前一个)
if(l_session != null && l_session.getId() != session.getId()){
MAP1.remove(sUserName);
MAP2.remove(l_session.getId());
l_session.setAttribute("msg", "您的账号已在另一处登录!");
MAP2.put(session.getId(), sUserName);
MAP1.put(sUserName, session);
}
//同一浏览器,同一用户(不做任何变动) }else{
//未登录
if(MAP2.containsKey(session.getId())){
//同一浏览器,不同用户(不做任何变动)
}else{
//不同浏览器,不同用户(正常添加)
MAP2.put(session.getId(), sUserName);
MAP1.put(sUserName, session);
}
} }

解释一下:这里使用username和userId效果一样,看你们怎么方便怎么用了,方法中的逻辑是根据上面的图来编写的,首先判断用户是否登录了,因为MAP中保存了相关的session关联信息,所以可以通过这个来判断;由于此处只对不同浏览器相同用户进行处理,所以直接判断是否是同一个浏览器。方法的参数session是用户在当前浏览器登录时的信息,我们可以从MAP中得到之前保存过的相同用户的session信息,与之进行比较,里面的逻辑是:移除MAP中保存的之前的用户信息(对应的session此时未销毁),并给其session添加一个msg信息(后面用到,往下看),再添加新的用户信息。

上面的方法调用放在登录验证成功后,各自项目不同,但登录验证的类基本差不多:


SessionListener.userLogin(session, USERNAME);

(2)添加前端页面调用的方法

在登录验证的类中添加如下方法:


/*
* 判断用户是否重复登录
*/
@RequestMapping(value="/checkUserOnline")
@ResponseBody
public void checkUserOnline(HttpServletRequest request,HttpServletResponse response) throws IOException{
HttpSession session=request.getSession();
PrintWriter out = response.getWriter();
String msg = "";
if(session.getAttribute("msg") != null){
msg = session.getAttribute("msg").toString();
System.out.println(msg);
}
out.print(session.getAttribute("msg"));
}

方法中获取之前添加到session中的msg,用来判断是否强制下线,继续。

(3)前端页面循环调用

选择一个页面,最好是所有页面都用到的,比如我用的index.jsp,如下:


<script type="text/javascript">
$(document).ready(function(){
setInterval("checkUserOnline()",5000); //每隔5秒判断一次
} function checkUserOnline(){
var msg = "";
$.ajax({
type : "POST",
url : "checkUserOnline",
data : {},
async: false,
success : function(data){
msg = data;
}
});
if (msg == 'null' || msg == '' || msg == 'undefined'){
return;
}else{
//调用你的注销用户方法
var url="<%=path%>/logout.do";
$.get(url,function(data){});
}
}
</script>

js中调用setInterval方法,设置调用的方法和间隔时间,方法里通过ajax调用上面添加的类并返回msg,通过msg来判断是否调用注销方法(路径啥的自己注意,能调用到就ok)。

(4)注销

一般web项目登录进去后都会有个退出按钮,点击即返回到登录页,此时在里面添加一行代码,防止错误,可能会出现重新登录报session已被销毁的错误提示,但第二次便会成功,这里便是为了消除该错误:


SessionListener.MAP2.remove(session.getId());

好了,基本的设置完成了,启动项目,打开两个不同的浏览器,先登录一个用户,成功后,在另一个浏览器中登录相同的用户,登录成功后,会在控制台上打印出msg:


您的账号已在另一处登录!

此时,刷新第一个浏览器用户登录界面,便会发现已经退出跳转到登录页了,大功告成!!!

原文链接:https://my.oschina.net/u/3747963/blog/1787633

Session管理之超时设置和强制下线的更多相关文章

  1. Spring Security 之Session管理配置

    废话不多说,直接上代码.示例如下: 1.   新建Maven项目  session 2.   pom.xml <project xmlns="http://maven.apache.o ...

  2. session 超时设置

    Java Web开发Session超时设置 博客分类: Java Web 在Java Web开发中,Session为我们提供了很多方便,Session是由浏览器和服务器之间维护的.Session超时理 ...

  3. session超时设置+超时页面跳转

    session超时设置,方法有三种: (1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(600);参数600单位是秒,即在没有10分钟活动后,sessio ...

  4. Shiro学习(10)Session管理

    Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如web容器tomcat),不管JavaSE还是JavaEE环境都可以使用,提供了会话管理.会话事件监听.会话存储/持久化.容器无关的集群. ...

  5. Redis-基本概念、java操作redis、springboot整合redis,分布式缓存,分布式session管理等

    NoSQL的引言 Redis数据库相关指令 Redis持久化相关机制 SpringBoot操作Redis Redis分布式缓存实现 Resis中主从复制架构和哨兵机制 Redis集群搭建 Redis实 ...

  6. 2016-1-30 Servlet中Session管理(Sesssion追踪)

    Session管理(Sesssion追踪)是Web应用程序开发中非常重要的一个主题.这是因为HTTP是无状态的,在默认情况下,Web服务器不知道一个HTTP请求是来自初次用户,还是来自之前已经访问过的 ...

  7. tomcat架构分析 (Session管理)

    Session管理是JavaEE容器比较重要的一部分,在app中也经常会用到.在开发app时,我们只是获取一个session,然后向session中存取数据,然后再销毁session.那么如何产生se ...

  8. Android学习笔记(十五)——实战:强制下线

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 实现强制下线功能的思路也比较简单,只需要在界面上弹出一个对话框, 让用户无法进行任何其他操作, 必须要点击对话 ...

  9. Tomcat的Session管理机制

    >>Session和Cookie请求的过程 Http连接本身是无状态的,即前一次发起的连接跟后一次没有任何关系,是属于两次独立的连接请求,但是互联网访问基本上都是需要有状态的,即服务器需要 ...

随机推荐

  1. FluentNhibernate 不支持存储过程

    一直以为没有使用FN进行存储过程的操作,这次因为后台首页想统计下数据,就利用了存储过程,但在使用中却发现FN目前还不支持存储过程(点击查看官方),没有办法,只能利用Fluent Configurati ...

  2. 回车(CR)换行(LF)的来历及区别

    转自https://blog.csdn.net/lw370481/article/details/8229344 一.回车”(Carriage Return)和“换行”(Line Feed)起源 回车 ...

  3. JQueryiframe页面操作父页面中的元素与方法(实例讲解)

    1)在iframe中查找父页面元素的方法:$('#id', window.parent.document) 2)在iframe中调用父页面中定义的方法和变量:parent.methodparent.v ...

  4. 用Python构建你自己的推荐系统

    用Python构建你自己的推荐系统 现如今,网站用推荐系统为你提供个性化的体验,告诉你买啥,吃啥甚至你应该和谁交朋友.尽管每个人口味不同,但大体都适用这个套路.人们倾向于喜欢那些与自己喜欢的其他东西相 ...

  5. 为golang程序使用pprof远程查看httpserver运行堆栈,cpu耗时等信息

    pprof是个神马玩意儿? pprof - manual page for pprof (part of gperftools) 是gperftools工具的一部分 gperftools又是啥? Th ...

  6. intel EPT 机制详解

    2016-11-08 在虚拟化环境下,intel CPU在处理器级别加入了对内存虚拟化的支持.即扩展页表EPT,而AMD也有类似的成为NPT.在此之前,内存虚拟化使用的一个重要技术为影子页表. 背景: ...

  7. VC2005 warning C4819 消除方法

    一. Warning C4819:The file contains a character that can ot be represented in the current code page(9 ...

  8. spring 自定义事物同步器(一): TransactionSynchronizationManager 解析

    一..JPA 获取 Hibernate的session try { session = entityManager.unwrap(Session.class); } catch (Exception ...

  9. django模型:字段和选项

    https://blog.csdn.net/iloveyin/article/details/44852645一.常用字段1.字段类型使用时需要引入django.db.models包,字段类型如下Au ...

  10. SQL Server扩展事件-- 使用system_health默认跟踪会话监控死锁

    SQL Server扩展事件(Extended Events)-- 使用system_health默认跟踪会话监控死锁 转自:http://blog.51cto.com/ultrasql/160037 ...