• session没有过期,其保存的数据无故丢失的原因


    问题:

    我们经常会做到的一个功能,将登录用户信息保存到session中,在页面上显示登录用户名。但是,如果很短时间内甚至几秒没有刷新这个页面的话,这个用户名就消失了,其实就是session中保存的用户数据丢失了。

    百度过很多,大部分说是session过期时间设置长一点,或者tomcat的配置问题等等,但都没能解决....在上一篇博客里问到这个问题的时候,有个博友的评论给了我思路,果然O(∩_∩)O哈哈~ 先感谢!!!

    然后 看测试过程吧 ↓↓↓

     

    下面这个是用户实体类:

     1 package com.lizhou.entity;
     2 
     3 /**
     4  * 用户类
     5  * @author bojiangzhou
     6  * @date 2016年2月28日
     7  */
     8 public class User {
     9     
    10     private int id;
    11     
    12     private String name;
    13 
    14     public User() {
    15         
    16     }
    17 
    18     public User(int id, String name) {
    19         this.id = id;
    20         this.name = name;
    21     }
    22 
    23     public int getId() {
    24         return id;
    25     }
    26 
    27     public void setId(int id) {
    28         this.id = id;
    29     }
    30 
    31     public String getName() {
    32         return name;
    33     }
    34 
    35     public void setName(String name) {
    36         this.name = name;
    37     }
    38     
    39 }

     

    用户servlet:地址栏输入http://localhost:8080/session/UserServlet进行访问,然后会重定向到showUser.jsp (这样刷新页面的时候就不会访问这个servlet了)

     1 package com.lizhou.servlet;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.ServletException;
     5 import javax.servlet.annotation.WebServlet;
     6 import javax.servlet.http.HttpServlet;
     7 import javax.servlet.http.HttpServletRequest;
     8 import javax.servlet.http.HttpServletResponse;
     9 
    10 import com.lizhou.entity.User;
    11 
    12 /**
    13  * 用户servlet
    14  * @author bojiangzhou
    15  * @date 2016年2月28日
    16  */
    17 public class UserServlet extends HttpServlet {
    18     private static final long serialVersionUID = 1L;
    19 
    20     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    21         request.setCharacterEncoding("UTF-8");
    22         
    23         User user = new User();
    24         user.setId(1);
    25         user.setName("Chiangchou");
    26         
    27         //将用户信息保存到session中
    28         request.getSession().setAttribute("user", user);
    29         //保存一个字符串信息
    30         request.getSession().setAttribute("message", "用户登录成功");
    31         
    32         //重定向
    33         response.sendRedirect("showUser.jsp");;
    34         
    35     }
    36 
    37     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    38         
    39     }
    40 
    41 }

    session监听器:监听session的创建与销毁、向session中添加属性、移除属性、更改属性。

     1 package com.lizhou.listener;
     2 
     3 import javax.servlet.http.HttpSessionAttributeListener;
     4 import javax.servlet.http.HttpSessionBindingEvent;
     5 import javax.servlet.http.HttpSessionEvent;
     6 import javax.servlet.http.HttpSessionListener;
     7 
     8 /**
     9  * session监听器
    10  * @author bojiangzhou
    11  * @date 2016年2月28日
    12  */
    13 public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
    14     
    15     //属性添加时间
    16     private long addTime;
    17     
    18     @Override
    19     public void sessionCreated(HttpSessionEvent event) {
    20         System.out.println("session 创建");
    21     }
    22 
    23     @Override
    24     public void sessionDestroyed(HttpSessionEvent event) {
    25         System.out.println("session 销毁");
    26     }
    27 
    28     @Override
    29     public void attributeAdded(HttpSessionBindingEvent event) {
    30         System.out.println("添加属性:"+event.getName());
    31         //当属性保存的时候保存当前时间
    32         addTime = System.currentTimeMillis();
    33     }
    34 
    35     @Override
    36     public void attributeRemoved(HttpSessionBindingEvent event) {
    37         System.out.println("移除属性:"+event.getName());
    38         //当属性移除的时候计算属性保存时间
    39         long removeTime = System.currentTimeMillis();
    40         long t = (removeTime-addTime)/1000;
    41         System.out.println("数据保存时间:"+t+"秒");
    42     }
    43 
    44     @Override
    45     public void attributeReplaced(HttpSessionBindingEvent event) {
    46         System.out.println("更改属性:"+event.getName());
    47     }
    48 
    49 }

    showUser.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 </head>
     9 <body>
    10     用户名:【 ${user.name} 】
    11     <br/>
    12     信息:【 ${message} 】
    13 </body>
    14 </html>

     

    准备工作做好了,下面看测试:

    首先直接在地址栏输入地址访问UserServlet,在doGet()里会将用户信息保存到session中,重定向到showUser.jsp时,显示用户名和信息,如图: 可以看到,User对象的属性和字符串都能显示。

     

    下面是控制台输出的信息:刚访问servlet后就截图的

     然后,过了一会,控制台如图:

     可以看到,54秒后,user属性移除了,message没有移除,session并没有销毁哦!!!然后刷新页面显示:这就是我们常见到的情况了....

     

    然后,百度大部分说设置session过期时间长一点:但是没有效果

    1 <!-- 设置session失效时间(单位:分) -->
    2 <session-config>
    3   <session-timeout>30</session-timeout>
    4 </session-config>

    然后还有一种方法:在根目录下放一个refresh.jsp文件,内容如下:主要是第6行代码,每隔一秒刷新一下,链接到自己

     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="refresh" content="1; url=refresh.jsp">
     7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     8 <title></title>
     9 </head>
    10 <body>
    11 
    12 </body>
    13 </html>

    然后在显示数据的页面(showUser.jsp)加上一句代码:<iframe width=0 height=0 src="refresh.jsp"></iframe>

    目的是不断请求服务器,我的理解是服务端以为客户端一直在使用这个对象,就不会移除这个数据了....

    这样虽然达到了目的,但有很大的弊端,而且治标不治本:一直请求服务器消耗服务器资源是肯定的了,而且浏览器的刷新图标会一直跳,看着很不爽的...

     

     *****************************************************************************************************************

     最后,看解决办法:只需要将User实现序列化接口Serializable即可,如下:

     1 package com.lizhou.entity;
     2 
     3 import java.io.Serializable;
     4 
     5 /**
     6  * 用户类
     7  * @author bojiangzhou
     8  * @date 2016年2月28日
     9  */
    10 public class User implements Serializable {
    11     
    12     private int id;
    13     
    14     private String name;
    15 
    16     public User() {
    17         
    18     }
    19 
    20     public User(int id, String name) {
    21         this.id = id;
    22         this.name = name;
    23     }
    24 
    25     //getter/setter方法26     
    27 }

    将要保存到session中的对象实现序列化接口Serializable,这样用户数据就一直保存在session里了,不管你怎么刷新,除非session销毁,数据一直都在!!!

    那么原因是什么呢?下面是我百度的一段:

    【Object serialization 允许你将实现了Serializable接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象。
    举个例子:网络传输的时候,可以传字符串,亦可以传对象object,例如socket。传字符串的时候接收方很容易解析出来,但是,传一个对象的时候,对方读完字节流后,不知道你传的什么对象,所以没办法给转成原来的对象并解析对象的属性,这时候就要用到序列化和反序列化。类实现序列化接口,socket发送这个对象的字节流,接收方收到流后就可以将流反序列化成对象,然后使用对象的方法和属性。】

     

    附上测试代码:session数据丢失测试代码

     OK!!!

     

  • 相关阅读:
    ubuntu基本命令篇13用户管理
    网易邮箱繁体字信件乱码解决
    ubuntu基本命令篇16网络管理
    Ubuntu 10.04的安装
    DotNetNuke模块开发(一)
    查询进程打开的文件(转)
    Shell 的变量(转)
    Boot loader: Grub进阶(转)
    bash的通配符与特殊符号
    shell下的作业管理(转)
  • 原文地址:https://www.cnblogs.com/chiangchou/p/session-timeout.html
Copyright © 2020-2023  润新知