JavaWeb之Session的序列化和反序列化 && Session的活化和钝化


  • 4506


应用场景:

需要重启,而用户会话还在进行相应的操作,这时就需要使用序列化将session信息保存起来放在硬盘,服务器重启后,又重新加载。这样就保证了用户信息不会丢失,实现永久化保存

活化、钝化,让其在闲置的时候离开内存,将信息保存至硬盘,等要用的时候,就重新加载进内存



一、session的序列化和反序列化

什么是序列化?

把对象的状态信息转换为可以存储或传输的形式过程,简单说就是把对象转换为字节形式存储的过程称为对象的序列化

什么是反序列化?

把字节序列转化为对象的过程


Tomcat下保存的session序列化文件

netty 序列化session至redis session序列化和反序列化_java


实现了Serializable接口的User类

1. import java.io.Serializable;  
2.   
3. public class User implements Serializable {  
4.   
5. private static final long serialVersionUID = 1L;  
6. private String username;  
7. private String password;  
8. public String getUsername() {  
9. return username;  
10.     }  
11. public void setUsername(String username) {  
12. this.username = username;  
13.     }  
14. public String getPassword() {  
15. return password;  
16.     }  
17. public void setPassword(String password) {  
18. this.password = password;  
19.     }  
20. @Override  
21. public String toString() {  
22. return "User [username=" + username + ", password=" + password + "]";  
23.     }  
24. public User() {  
25. super();  
26.     }  
27. public User(String username, String password) {  
28. super();  
29. this.username = username;  
30. this.password = password;  
31.     }  
32. }



向session中存放数据的a.jsp

1. <%@page import="cn.cil.domain.User"%>  
2. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
3. <%  
4. String path = request.getContextPath();  
5. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
6. %>  
7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
8. <html>  
9.   <head>  
10. "<%=basePath%>">  
11.       
12. 'a.jsp' starting page</title>  
13.       
14. "pragma" content="no-cache">  
15. "cache-control" content="no-cache">  
16. "expires" content="0">      
17. "keywords" content="keyword1,keyword2,keyword3">  
18. "description" content="This is my page">  
19.   
20.   </head>  
21.     
22.   <body>  
23.     <h1>向 Session 存放资源</h1>  
24.     <%  
25. new User("123","abc");  
26. "user",user);  
27.     %>  
28.   </body>  
29. </html>  
30. </strong></span>


取数据的b.jsp

1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
2. <%  
3. String path = request.getContextPath();  
4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
5. %>  
6.   
7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
8. <html>  
9.   <head>  
10. "<%=basePath%>">  
11.       
12. 'b.jsp' starting page</title>  
13.       
14. "pragma" content="no-cache">  
15. "cache-control" content="no-cache">  
16. "expires" content="0">      
17. "keywords" content="keyword1,keyword2,keyword3">  
18. "description" content="This is my page">  
19.   
20.   </head>  
21.     
22.   <body>  
23.     <h1>从 Seesion 中取资源</h1>  
24. "user") %>  
25.   </body>  
26. </html>  
27. </strong></span>

在向seesion保存资源后(访问a.jsp后),关闭tomcat,然后迅速打开tomcat的work目录到指定项目文件中,就会看到生成的Sessions.ser文件,这个文件保存的就是所有session对象序列化后的信息

这时,再重启Tomcat,会看到SESSIONS.ser文件消失,又被重新加载,再访问b.jsp,原来的对象信息还在



模拟对象的序列化反序列化

1. import java.io.File;  
2. import java.io.FileInputStream;  
3. import java.io.FileOutputStream;  
4. import java.io.ObjectInputStream;  
5. import java.io.ObjectOutputStream;  
6.   
7. import org.junit.Test;  
8.   
9. import cn.cil.domain.User;  
10.   
11.   
12. public class TestSerializable {  
13.   
14. @Test  
15. public void test() throws Exception {  
16.           
17. new User("123","abc");  
18.         SerializeObj(user);  
19.         User users = ObjDeSerialize();  
20.         System.out.println(users);  
21.     }  
22.       
23. private void SerializeObj(User user) throws Exception{  
24.           
25. new ObjectOutputStream(  
26. new FileOutputStream(new File("G:/SESSIONS.ser")));  
27.         outObj.writeObject(user);  
28. "对象序列化完成");  
29.     }  
30.       
31. private User ObjDeSerialize() throws Exception{  
32. new ObjectInputStream(new FileInputStream(  
33. new File("G:/SESSIONS.ser")));  
34.         User user = (User)inObj.readObject();  
35. "对象反序列化完成");  
36. return user;  
37.     }  
38.   
39. }



netty 序列化session至redis session序列化和反序列化_User_02





特别注意:

1.进行对象的序列化和反序列化的对象,必须实现Serializable接口,否则无法进行序列化和反序列化,当然这仅仅可以进行序列化和反序列化而已,如果序列化完成的对象(已经保存至硬盘),反序列化前又修改了对象,那么反序列化会失败,所以进行序列化的对象必须还要添加serialVersionUID

1. public class User implements Serializable{   
2.   
3. //private static final long serialVersionUID = 1L; //不添加ID  
4. private String username;  
5. private String password;  
6. //private int age = 10; 对象序列化后,新增内容  
7.       
8. public String getUsername() {  
9. return username;  
10.     }  
11. public void setUsername(String username) {  
12. this.username = username;  
13.     }  
14. public String getPassword() {  
15. return password;  
16.     }  
17. public void setPassword(String password) {  
18. this.password = password;  
19.     }  
20.       
21.   
22.       
23. /*@Override
24.     public String toString() {
25.         return "User [username=" + username + ", password=" + password
26.                 + ", age=" + age + "]";
27.     }*/  
28.       
29. /*@Override
30.     public String toString() {
31.         return "User [username=" + username + ", password=" + password
32.                 + "]";
33.     }*/  
34. public User() {  
35. super();  
36.     }  
37. public User(String username, String password) {  
38. super();  
39. this.username = username;  
40. this.password = password;  
41.     }  
42. }  
43.   
44.   
45. @Test  
46. public void test2() throws Exception {  
47.           
48. new User("123","abc");  
49.           
50.         SerializeObj(user);  
51.           
52.     }  
53. @Test  
54. public void test3() throws Exception {  
55.           
56.         User users = ObjDeSerialize();  
57.         System.out.println(users);  
58.           
59.     }  
60. </strong></span>



在反序列化前,打开注释部分,进行反序列化


netty 序列化session至redis session序列化和反序列化_java_03

这也就说明了,文件流中的class和web下的classpath中的class(修改后)不一致了,会抛出异常,所以进行序列化的对象,如果需要在修改后还可以进行反序列化,就必须添加serialVersionUID,如果不指定serialVersionUID,java编译器会自动帮我们添加,一个对象只要修改一点点,他们的serialVersionUID就会不一致,序列化前是一个serialVersionUID,反序列化又是一个serialVersionUID,两个serialVersionUID不一致,肯定会异常。Eclipse如此强大,不填写serialVersionUID时,它会报警。所以稍稍注意一下。

2.如果一个对象不实现Serializable接口,它是无法进行序列化的,根本就无法转换为字节序列

实现Serializable接口,就好比坐飞机的机票,有机票带你飞,没票在地上呆着

netty 序列化session至redis session序列化和反序列化_java_04

二、session的活化和钝化

当一个用户长时间不进行操作的时,服务器为减轻内存压力,可以将其session保存到硬盘中,等待用户再次操作的时候,再从硬盘中取出来,(保存到硬盘中的信息不会删除)

将下面配置文件放到tomcat\conf\catalina\localhost目录下!文件名称为项目名称。

1. <Context>  
2. <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"[如果session在1分钟内没有使用,那么Tomcat就会钝化它]>  
3. <Store className="org.apache.catalina.session.FileStore" directory="mysession"[把session序列化到Tomcat\work\Catalina\localhost\listener\mysession目录下。]/>  
4. </Manager>  
5. </Context>


当然也可以放到tomcat的config下的context.xml中,这样就是对Tomcat下所有应用都生效

netty 序列化session至redis session序列化和反序列化_java_05



应用场景:

需要重启,而用户会话还在进行相应的操作,这时就需要使用序列化将session信息保存起来放在硬盘,服务器重启后,又重新加载。这样就保证了用户信息不会丢失,实现永久化保存

活化、钝化,让其在闲置的时候离开内存,将信息保存至硬盘,等要用的时候,就重新加载进内存



一、session的序列化和反序列化

什么是序列化?

把对象的状态信息转换为可以存储或传输的形式过程,简单说就是把对象转换为字节形式存储的过程称为对象的序列化

什么是反序列化?

把字节序列转化为对象的过程


Tomcat下保存的session序列化文件

netty 序列化session至redis session序列化和反序列化_java


实现了Serializable接口的User类

1. import java.io.Serializable;  
2.   
3. public class User implements Serializable {  
4.   
5. private static final long serialVersionUID = 1L;  
6. private String username;  
7. private String password;  
8. public String getUsername() {  
9. return username;  
10.     }  
11. public void setUsername(String username) {  
12. this.username = username;  
13.     }  
14. public String getPassword() {  
15. return password;  
16.     }  
17. public void setPassword(String password) {  
18. this.password = password;  
19.     }  
20. @Override  
21. public String toString() {  
22. return "User [username=" + username + ", password=" + password + "]";  
23.     }  
24. public User() {  
25. super();  
26.     }  
27. public User(String username, String password) {  
28. super();  
29. this.username = username;  
30. this.password = password;  
31.     }  
32. }

 



向session中存放数据的a.jsp

1. <%@page import="cn.cil.domain.User"%>  
2. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
3. <%  
4. String path = request.getContextPath();  
5. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
6. %>  
7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
8. <html>  
9.   <head>  
10. "<%=basePath%>">  
11.       
12. 'a.jsp' starting page</title>  
13.       
14. "pragma" content="no-cache">  
15. "cache-control" content="no-cache">  
16. "expires" content="0">      
17. "keywords" content="keyword1,keyword2,keyword3">  
18. "description" content="This is my page">  
19.   
20.   </head>  
21.     
22.   <body>  
23.     <h1>向 Session 存放资源</h1>  
24.     <%  
25. new User("123","abc");  
26. "user",user);  
27.     %>  
28.   </body>  
29. </html>  
30. </strong></span>


取数据的b.jsp

1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
2. <%  
3. String path = request.getContextPath();  
4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
5. %>  
6.   
7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
8. <html>  
9.   <head>  
10. "<%=basePath%>">  
11.       
12. 'b.jsp' starting page</title>  
13.       
14. "pragma" content="no-cache">  
15. "cache-control" content="no-cache">  
16. "expires" content="0">      
17. "keywords" content="keyword1,keyword2,keyword3">  
18. "description" content="This is my page">  
19.   
20.   </head>  
21.     
22.   <body>  
23.     <h1>从 Seesion 中取资源</h1>  
24. "user") %>  
25.   </body>  
26. </html>  
27. </strong></span>





在向seesion保存资源后(访问a.jsp后),关闭tomcat,然后迅速打开tomcat的work目录到指定项目文件中,就会看到生成的Sessions.ser文件,这个文件保存的就是所有session对象序列化后的信息

这时,再重启Tomcat,会看到SESSIONS.ser文件消失,又被重新加载,再访问b.jsp,原来的对象信息还在



模拟对象的序列化反序列化


1. import java.io.File;  
2. import java.io.FileInputStream;  
3. import java.io.FileOutputStream;  
4. import java.io.ObjectInputStream;  
5. import java.io.ObjectOutputStream;  
6.   
7. import org.junit.Test;  
8.   
9. import cn.cil.domain.User;  
10.   
11.   
12. public class TestSerializable {  
13.   
14. @Test  
15. public void test() throws Exception {  
16.           
17. new User("123","abc");  
18.         SerializeObj(user);  
19.         User users = ObjDeSerialize();  
20.         System.out.println(users);  
21.     }  
22.       
23. private void SerializeObj(User user) throws Exception{  
24.           
25. new ObjectOutputStream(  
26. new FileOutputStream(new File("G:/SESSIONS.ser")));  
27.         outObj.writeObject(user);  
28. "对象序列化完成");  
29.     }  
30.       
31. private User ObjDeSerialize() throws Exception{  
32. new ObjectInputStream(new FileInputStream(  
33. new File("G:/SESSIONS.ser")));  
34.         User user = (User)inObj.readObject();  
35. "对象反序列化完成");  
36. return user;  
37.     }  
38.   
39. }



netty 序列化session至redis session序列化和反序列化_User_02





特别注意:

1.进行对象的序列化和反序列化的对象,必须实现Serializable接口,否则无法进行序列化和反序列化,当然这仅仅可以进行序列化和反序列化而已,如果序列化完成的对象(已经保存至硬盘),反序列化前又修改了对象,那么反序列化会失败,所以进行序列化的对象必须还要添加serialVersionUID




1. public class User implements Serializable{   
2.   
3. //private static final long serialVersionUID = 1L; //不添加ID  
4. private String username;  
5. private String password;  
6. //private int age = 10; 对象序列化后,新增内容  
7.       
8. public String getUsername() {  
9. return username;  
10.     }  
11. public void setUsername(String username) {  
12. this.username = username;  
13.     }  
14. public String getPassword() {  
15. return password;  
16.     }  
17. public void setPassword(String password) {  
18. this.password = password;  
19.     }  
20.       
21.   
22.       
23. /*@Override
24.     public String toString() {
25.         return "User [username=" + username + ", password=" + password
26.                 + ", age=" + age + "]";
27.     }*/  
28.       
29. /*@Override
30.     public String toString() {
31.         return "User [username=" + username + ", password=" + password
32.                 + "]";
33.     }*/  
34. public User() {  
35. super();  
36.     }  
37. public User(String username, String password) {  
38. super();  
39. this.username = username;  
40. this.password = password;  
41.     }  
42. }  
43.   
44.   
45. @Test  
46. public void test2() throws Exception {  
47.           
48. new User("123","abc");  
49.           
50.         SerializeObj(user);  
51.           
52.     }  
53. @Test  
54. public void test3() throws Exception {  
55.           
56.         User users = ObjDeSerialize();  
57.         System.out.println(users);  
58.           
59.     }  
60. </strong></span>



在反序列化前,打开注释部分,进行反序列化


netty 序列化session至redis session序列化和反序列化_java_03

这也就说明了,文件流中的class和web下的classpath中的class(修改后)不一致了,会抛出异常,所以进行序列化的对象,如果需要在修改后还可以进行反序列化,就必须添加serialVersionUID,如果不指定serialVersionUID,java编译器会自动帮我们添加,一个对象只要修改一点点,他们的serialVersionUID就会不一致,序列化前是一个serialVersionUID,反序列化又是一个serialVersionUID,两个serialVersionUID不一致,肯定会异常。Eclipse如此强大,不填写serialVersionUID时,它会报警。所以稍稍注意一下。

2.如果一个对象不实现Serializable接口,它是无法进行序列化的,根本就无法转换为字节序列

实现Serializable接口,就好比坐飞机的机票,有机票带你飞,没票在地上呆着

netty 序列化session至redis session序列化和反序列化_java_04

二、session的活化和钝化

当一个用户长时间不进行操作的时,服务器为减轻内存压力,可以将其session保存到硬盘中,等待用户再次操作的时候,再从硬盘中取出来,(保存到硬盘中的信息不会删除)

将下面配置文件放到tomcat\conf\catalina\localhost目录下!文件名称为项目名称。

1. <Context>  
2. <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"[如果session在1分钟内没有使用,那么Tomcat就会钝化它]>  
3. <Store className="org.apache.catalina.session.FileStore" directory="mysession"[把session序列化到Tomcat\work\Catalina\localhost\listener\mysession目录下。]/>  
4. </Manager>  
5. </Context>


当然也可以放到tomcat的config下的context.xml中,这样就是对Tomcat下所有应用都生效

netty 序列化session至redis session序列化和反序列化_java_05