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( id,String name) {
19         this.id =20         this.name = name;
21 22 
23      getId() {
24         return25 26 
27     void setId( id) {
28         29 30 
31      String getName() {
32         33 34 
35     void setName(String name) {
36         37 38     
39 }

 

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

 com.lizhou.servlet;
import java.io.IOException;
 javax.servlet.ServletException;
 javax.servlet.annotation.WebServlet;
 javax.servlet.http.HttpServlet;
 7  javax.servlet.http.HttpServletRequest;
 javax.servlet.http.HttpServletResponse;
 9 
10  com.lizhou.entity.User;
11 
12 13  * 用户servlet
14 15 16  17 class UserServlet extends HttpServlet {
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(125         user.setName("Chiangchou"26         
27         //将用户信息保存到session中
28         request.getSession().setAttribute("user",user);
29         保存一个字符串信息
30         request.getSession().setAttribute("message","用户登录成功"31         
重定向
33         response.sendRedirect("showUser.jsp");;
34         
35 36 
37     void doPost(HttpServletRequest request,1)">38         
39 40 
41 }

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

 com.lizhou.listener;
 javax.servlet.http.HttpSessionAttributeListener;
 javax.servlet.http.HttpSessionBindingEvent;
 javax.servlet.http.HttpSessionEvent;
 javax.servlet.http.HttpSessionListener;
 7 
 9  * session监听器
11 12  class SessionListener implements HttpSessionListener,HttpSessionAttributeListener {
14     
15     属性添加时间
16     long addTime;
17     
18     @Override
19      sessionCreated(HttpSessionEvent event) {
20         System.out.println("session 创建"23 24      sessionDestroyed(HttpSessionEvent event) {
25         System.out.println("session 销毁"26 27 
28 29      attributeAdded(HttpSessionBindingEvent event) {
30         System.out.println("添加属性:"+event.getName());
31         当属性保存的时候保存当前时间
32         addTime = System.currentTimeMillis();
36      attributeRemoved(HttpSessionBindingEvent event) {
37         System.out.println("移除属性:"+38         当属性移除的时候计算属性保存时间
39         long removeTime =40         long t = (removeTime-addTime)/100041         System.out.println("数据保存时间:"+t+"秒"42 43 
44 45      attributeReplaced(HttpSessionBindingEvent event) {
46         System.out.println("更改属性:"+47 48 
49 }

showUser.jsp 显示用户名

 1 <%@ page language="java contentTypetext/html; charset=UTF-8"
 2     pageEncodingUTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<htmlheadmeta http-equiv="Content-Type" content="text/html; charset=UTF-8"title>显示用户</body    用户名:【 ${user.name} 】
11     br/>
    信息:【 ${message} 】
>

 

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

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

 

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

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

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

 

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

1 <!-- 设置session失效时间(单位:分) -->
2 session-config3   session-timeout>304 >

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

="refresh"="1; url=refresh.jsp"></>

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

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

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

 

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

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

 java.io.Serializable;
 4 
 9  class User  Serializable {
13     
15 
17         
21         22         24 
25     //getter/setter方法26     
27 }

 

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

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

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

 

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

 OK!!!

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&amp;FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = &quot;hello&quot;; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let&#39;s briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越