Session的序列化和反序列化

论坛 期权论坛 脚本     
匿名技术用户   2021-1-5 08:50   14   0

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


应用场景:

1.一般来说,服务器启动后,就不会再关闭了,但是如果逼不得已需要重启,而用户会话还在进行相应的操作,这时就需要使用序列化将session信息保存起来放在硬盘,服务器重启后,又重新加载。这样就保证了用户信息不会丢失,实现永久化保存

2.淘宝每年都会有定时抢购的活动,很多用户会提前登录等待,长时间不进行操作,一致保存在内存中,而到达指定时刻,几十万用户并发访问,就可能会有几十万个session,内存可能吃不消,这时就需要进行对象的活化、钝化,让其在闲置的时候离开内存,将信息保存至硬盘,等要用的时候,就重新加载进内存


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

什么是序列化?

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

什么是反序列化?

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


Tomcat下保存的session序列化文件



实现了Serializable接口的User类

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

向session中存放数据的a.jsp

[java] view plain copy
  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. <base href="<%=basePath%>">
  11. <title>My JSP 'a.jsp' starting page</title>
  12. <meta http-equiv="pragma" content="no-cache">
  13. <meta http-equiv="cache-control" content="no-cache">
  14. <meta http-equiv="expires" content="0">
  15. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  16. <meta http-equiv="description" content="This is my page">
  17. </head>
  18. <body>
  19. <h1>向 Session 存放资源</h1>
  20. <%
  21. User user = new User("123","abc");
  22. session.setAttribute("user",user);
  23. %>
  24. </body>
  25. </html>
  26. </strong></span>
取数据的b.jsp

[java] view plain copy
  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. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  7. <html>
  8. <head>
  9. <base href="<%=basePath%>">
  10. <title>My JSP 'b.jsp' starting page</title>
  11. <meta http-equiv="pragma" content="no-cache">
  12. <meta http-equiv="cache-control" content="no-cache">
  13. <meta http-equiv="expires" content="0">
  14. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  15. <meta http-equiv="description" content="This is my page">
  16. </head>
  17. <body>
  18. <h1>从 Seesion 中取资源</h1>
  19. <%= session.getAttribute("user") %>
  20. </body>
  21. </html>
  22. </strong></span>

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

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


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

[java] view plain copy
  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. import org.junit.Test;
  7. import cn.cil.domain.User;
  8. public class TestSerializable {
  9. @Test
  10. public void test() throws Exception {
  11. User user = new User("123","abc");
  12. SerializeObj(user);
  13. User users = ObjDeSerialize();
  14. System.out.println(users);
  15. }
  16. private void SerializeObj(User user) throws Exception{
  17. ObjectOutputStream outObj = new ObjectOutputStream(
  18. new FileOutputStream(new File("G:/SESSIONS.ser")));
  19. outObj.writeObject(user);
  20. System.out.println("对象序列化完成");
  21. }
  22. private User ObjDeSerialize() throws Exception{
  23. ObjectInputStream inObj = new ObjectInputStream(new FileInputStream(
  24. new File("G:/SESSIONS.ser")));
  25. User user = (User)inObj.readObject();
  26. System.out.println("对象反序列化完成");
  27. return user;
  28. }
  29. }


特别注意:

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


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

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


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

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

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


二、session的活化和钝化

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

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

[html] view plain copy
  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下所有应用都生效



分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP