您现在的位置: 365建站网 > 365文章 > session超时失效的时间控制机制

session超时失效的时间控制机制

文章来源:365jz.com     点击数:1487    更新时间:2019-06-20 17:25   参与评论

在web开发中,session是个非常重要的概念。在许多动态网站的开发者看来,session就是一个变量,而且其表现像个黑洞,他只需要将东西在合适的时机放进这个洞里,等需要的时候再把东西取出来。这是开发者对session最直观的感受,但是黑洞里的景象或者说session内部到底是怎么工作的呢?当笔者向身边的一些同事或朋友问及相关的更进一步的细节时,很多人往往要么含糊其辞要么主观臆断,所谓知其然而不知其所以然。

笔者由此想到很多开发者,包括我自己,每每都是纠缠于框架甚至二次开发平台之上,而对于其下的核心和基础知之甚少,或者有心无力甚至毫不关心,少了逐本溯源的精神,每忆及此,无不惭愧。曾经实现过一个简单的HttpServer,但当时由于知识储备和时间的问题,没有考虑到session这块,不过近期在工作之余翻看了一些资料,并进行了相关实践,小有所得,本着分享的精神,我将在本文中尽可能全面地将个人对于session的理解展现给读者,同时尽我所能地论及一些相关的知识,以期读者在对session有所了解的同时也能另有所悟,正所谓授人以渔。

Session是什么
    Session一般译作会话,牛津词典对其的解释是进行某活动连续的一段时间。从不同的层面看待session,它有着类似但不全然相同的含义。比如,在web应用的用户看来,他打开浏览器访问一个电子商务网站,登录、并完成购物直到关闭浏览器,这是一个会话。而在web应用的开发者开来,用户登录时我需要创建一个数据结构以存储用户的登录信息,这个结构也叫做session。因此在谈论session的时候要注意上下文环境。而本文谈论的是一种基于HTTP协议的用以增强web应用能力的机制或者说一种方案,它不是单指某种特定的动态页面技术,而这种能力就是保持状态,也可以称作保持会话。

在一般系统登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session

具体设置的方法有三种:

1.在web容器中设置(以tomcat为例)

在tomcat-7.0\conf\web.xml中设置,以下是tomcat7.0中默认配置:

<session-config>

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

</session-config>

tomcat默认session超时时间为30分钟,可以根据需要修改,负数或0为不限制session失效时间


这里要注意这个session设置的时间是根据服务器来计算的,而不是客户端。所以如果在调试程序,应该是修改服务器端时间来测试,而不是客户端


2.在工程的web.xml中设置

<!--时间单位为分钟-->

<session-config>

<session-timeout>15</session-timeout>

</session-config>

 这里的15是指15分钟失效


3.通过java代码设置

session.setMaxInactiveInterval(30*60);//以秒为单位,即在没有活动30分钟后,session将失效


三种方式优先等级:1 < 2 < 3


在一般系统中,也可能需要在session失效后做一些操作:

1.控制用户数,当session失效后,系统的用户数减少一个,控制用户数量在一定范围内,确保系统的性能

2.控制一个用户多次登录,当session有效时,如果相同用户登录,就提示已经登录了,当session失效后,就可以不同提示,直接登录

那么如何在session失效后,进行一系列的操作呢?

这里就需要用到监听器了,即当session因为各种原因失效后,监听器就可以监听到,然后执行监听器中定义好的程序就可以了

监听器类为:HttpSessionListener类,有sessionCreated和sessionDestroyed两个方法

自己可以继承这个类,然后分别实现

sessionCreated指在session创建时执行的方法

sessionDestroyed指在session失效时执行的方法

例子:

</>code

  1. public class OnlineUserListener implements HttpSessionListener{
  2.     public void sessionCreated(HttpSessionEvent event){
  3.         HttpSession session=event.getSession;
  4.         String id=session.getId()+session.getCreationTime();
  5.         SummerConstant.UserMap.put(id,Boolean.TRUE);//添加用户
  6.     }
  7.     
  8.     public void sessionDestroyed(HttpSessionEvent event){
  9.         HttpSession session=event.getSession;
  10.         String id=session.getId()+session.getCreationTime();
  11.         synchronized(this){
  12.             SummerConstant.USERNum--;//用户数减-
  13.             SummerConstant.UserMap.remove(id);//从用户组中移除掉,用户组为一个map
  14.         }
  15.     }
  16. }

然后只需要把这个监听器在web.xml中声明就可以了

<listener>

<listener-class>com.demo.OnlineUserListener</listener-class>

</listener>


1."在一次做非常复杂的ajax应用时,如果一个会话已经超时,但是此时再通过ajax请求,那么ajax返回的则是一个登陆页面的html,那这下就惨了,页面上而已就乱了"
2."对于普通的http请求,可以通过过滤器Filter来判断session超时,然后跳转到登录页面;但是对于Ajax请求,则不会如期待的那样自动转到登录页面(我试了网站上的许多种方案,都是停留在当前页面)"
3.Ajax请求后台数据虽然会被过滤器filter拦截,但是因为Ajax操作与对页面整个页面的提交请求不一样,filter中的重定向并不能使之跳到一个新的页面,因此需要我们去做特殊的处理。处理原理很简单,如果session超时,filter返回一个超时标识给客户端,客户端检测到超时头信息,跳转到指定页面。
4.当session超时时,如果不是ajax请求,很简单就能实现跳到指定的页面;但是ajax请求就会有问题:如果是ajax类型的弹出框则会在弹出框中显示跳转的指定页面,如果是正常ajax请求,则可能会显示源代码等。
5.http://www.iteye.com/topic/1126552
6.http://www.cnblogs.com/shencheng/archive/2011/01/07/1930227.html
7.区分ajax请求和普通http请求:session超时处理、exception处理


---sessionListener

web.xml:


</>code

  1.     <session-config> 
  2.        <session-timeout>1</session-timeout> <!--单位min,若为-1则永远不超时-->
  3.     </session-config> 
  4.     
  5.     <listener>
  6.        <listener-class>test.MyHttpSessionListener</listener-class>
  7.     </listener>

Listener:

</>code

  1. public class MyHttpSessionListener implements HttpSessionListener {  
  2. //创建  
  3. public void sessionCreated(HttpSessionEvent arg0) {  
  4. System.out.println("sessionCreated..........");  
  5. }  
  6. //销毁
  7. public void sessionDestroyed(HttpSessionEvent arg0) {  
  8. System.out.println("sessionDestroyed........");  
  9. }  
  10. }

---session过期判断:跳转到登录页面
web.xml:(配置在springmvc的拦截之前)

</>code

  1.   <filter>
  2.       <filter-name>sessionFilter</filter-name>
  3.       <filter-class>test.SessionFilter</filter-class> 
  4.   </filter>
  5.   <filter-mapping>
  6.       <filter-name>sessionFilter</filter-name>
  7.       <url-pattern>/user/*</url-pattern>
  8.   </filter-mapping>

Filter:

</>code

  1. public class SessionFilter implements Filter {
  2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
  3. ServletException {
  4. if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
  5. throw new ServletException("OncePerRequestFilter just supports HTTP requests");
  6. }
  7.  
  8. HttpServletRequest req = (HttpServletRequest) request;
  9. HttpServletResponse res = (HttpServletResponse) response;
  10. //
  11. String userId = (String) req.getSession().getAttribute("userId");
  12. //
  13. if ((userId == null) || "".equals(userId)) {
  14. //
  15. res.sendRedirect(req.getContextPath() + "/loginDemo");
  16. //
  17. }
  18. System.out.println("判断: " + req.getSession(false));
  19. if (null == req.getSession(false)) {
  20. //
  21. if (true == req.getSession(true).isNew()) {
  22. //
  23. System.out.println("new request");
  24. //
  25. System.out.println("session已经过期");
  26. if (req.getHeader("x-requested-with") != null 
  27. && req.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {  
  28. System.out.println("ajax超时处理..............");
  29. res.addHeader("sessionstatus", "timeout");   
  30. res.addHeader("loginPath","loginurl");
  31. res.setCharacterEncoding("utf-8");
  32.             res.setContentType("text/html;charset=UTF-8");
  33.             OutputStream out = response.getOutputStream();
  34.             PrintWriter pw = new PrintWriter(new OutputStreamWriter(out,"utf-8"));
  35.             pw.println("{\"result\":false,\"errorMessage\":\"您未登录,请先登录\"}");
  36.             pw.flush();
  37.             pw.close();
  38. //前端js处理
  39.             return;
  40. }else{
  41. System.out.println("http超时处理.............");
  42. res.sendRedirect(req.getContextPath() + "/index.page");
  43. return;
  44. } else{
  45. System.out.println("Session is active!");
  46. }
  47. System.out.println("sessionFilter doFilter..........");
  48. chain.doFilter(request, response);
  49. }
  50. public void destroy() {
  51. }
  52. public void init(FilterConfig filterConfig) {
  53. }
  54. }

--前端JS处理:

</>code

  1. $(document).ajaxComplete(function(event, xhr, settings) {
  2. if(xhr.getResponseHeader("sessionstatus")=="timeOut"){
  3. if(xhr.getResponseHeader("loginPath")){
  4. window.location.replace(xhr.getResponseHeader("loginPath"));
  5. }else{
  6. alert("Request time out relogin plase !");
  7. }
  8. }
  9. }); 
  10. //全局的ajax访问,处理ajax清求时sesion超时
  11. $.ajaxSetup({
  12. contentType:"application/x-www-form-urlencoded;charset=utf-8",
  13. complete:function(XMLHttpRequest,textStatus){
  14. //通过XMLHttpRequest取得响应头,sessionstatus,
  15. var sessionstatus=XMLHttpRequest.getResponseHeader("sessionstatus"); 
  16. if(sessionstatus=="timeout"){
  17. //如果超时就处理 ,指定要跳转的页面
  18. window.location = "<c:url value="/" />";
  19. }
  20. }
  21. });


如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (1487人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号