后台登录信息市保存在session好一点还是redis好一点?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后台登录信息市保存在session好一点还是redis好一点?相关的知识,希望对你有一定的参考价值。
首先你要明白session和redis的差别在哪里,session是存在服务器端的一个变量,有自己的生命周期。redis一般是进行缓存的,应用场景是比如你每次请求的数据量很大,在进行首次操作的时候写入再次访问的时候就不会调用数据接口,而是直接取出缓存的数据以达到快速的响应。追问
分布式的时候session是否会丢失
参考技术A session在本地内存中,2个ajax请求所用时间差不多,用sessionState 和redis 2个ajax请求中第一个正常,第二个明显要慢。微软自带的sessionState 和redis session性能差距不大。我曾经做过测试 这里就不贴图了, 直接说结果。 在用redis做session管理的时候,2个ajax 在begin_request时间基本一致,但是到达action的时间就有差距了,就像上面的截图一样,相差 在500毫秒左右, 所以差距处在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!!!
以上是关于后台登录信息市保存在session好一点还是redis好一点?的主要内容,如果未能解决你的问题,请参考以下文章