程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> session沒有過期,其保存的數據無故丟失的原因,session過期

session沒有過期,其保存的數據無故丟失的原因,session過期

編輯:JAVA綜合教程

session沒有過期,其保存的數據無故丟失的原因,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!!!

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved