Spring Session Redis最佳实践(二)Redis中的数据存储
Spring Sessionadmin 发布于:2019-05-25 19:04:03
阅读:loading
前一文我通过一些示例实践实现了一个较为简单的Spring Session Redis的数据管理,本篇主要说一下Session数据存储在Redis中的数据结构及使用Jedis进行一些小小的Junit测试一下,将存储至Redis中的数据读取出来,通过读取后的数据结构来了解它的存储。
对于JDBC存储至表中的Session数据我们易于管理,直接通过查询表数据的方式即可,但存储至Redis中的Session数据存储,我也是耗费了许久时间才略有一些浅浅的总结,如果你有注意到前篇文章中的一些Redis数据查看命令与截图,兴许就有此一问,这里面的数据都是啥啊,看不懂是正常的,这说明Redis中存储的Session数据默认是采用JDK自带的序列化存储的,界面上看到的session数据都是从Redis中获取出来,并且通过JDK的反序列化解出来显示的,下面专门针对于一个session ID与session中存储的数据(包含字符串类型值与Java对象类型),去了解它的序列化存储,参考Session ID与Session中存储的数据截图如下:
Redis中查看这个session ID中存储的数据结构图,可以看出奇数行号的为session数据对象的属性,带sessionAttr开头的则为session中存储的参数信息,sessionAttr:K1为字符串类型,sessionAttr:point存储的为java.awt.Point类型的对象,但是实际上的数值(偶数行)则无法识别了,参考如下图:
通过Jedis提供的API可以用来获取Redis中的数据,如果想要将上图中的数据显示出来,则需要使用到JDK的反序列化,而这个反序列化的方式本文就采用spring-data-redis中提供的实现类,可参见“org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”类的实现,本例中就通过调用Redis命令一致的函数实现,具体参考如下代码所示:
(1)测试某个session ID的所有Key
//测试获得某个session ID的所有key
@Test
public void testSessionIdKeys() throws Exception {
String sessionId = "spring:session:sessions:" + ID;
Boolean exists = jedis.exists(sessionId);
if(! exists){
return;
}
String type = jedis.type(sessionId);
System.out.println("sessionId的数值类型为:" + type);
Map<String, String> sessions = jedis.hgetAll(sessionId);
System.out.println("sessionId所有key为:" + sessions.keySet());
Set<Map.Entry<String , String>> entrySet = sessions.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey() + "--" + entry.getValue());
}
}
-----------------------testSessionIdKeys输出结果为-------------------
[lastAccessedTime, sessionAttr:point, sessionAttr:K1, maxInactiveInterval, creationTime]
lastAccessedTime--�� sr java.lang.Long;��̏#� J valuexr java.lang.Number������ xp j�۹�
sessionAttr:point--�� sr java.awt.Point�Ċr4~�& I xI yxp '
sessionAttr:K1--�� t V1
maxInactiveInterval--�� sr java.lang.Integer⠤���8 I valuexr java.lang.Number������ xp
creationTime--�� sr java.lang.Long;��̏#� J valuexr java.lang.Number������ xp j���j
-----------------------testSessionIdKeys输出结果为-------------------
说明:本例获取的session ID中的所有key数据以及key对应的value字符串值。
(2)测试某个session ID的所有数据
//测试某个session ID的所有数据
@Test
public void testSessionAllValue(){
String sessionId = "spring:session:sessions:" + ID;
Map<byte[] , byte[]> map = jedis.hgetAll(sessionId.getBytes());
JdkSerializationRedisSerializer jdk = new JdkSerializationRedisSerializer();
for (Map.Entry<byte[], byte[]> entry : map.entrySet()) {
Object value = jdk.deserialize(entry.getValue());
System.out.println(value.getClass() + "---" + new String(entry.getKey()) + "---" + value);
}
}
-----------------------testSessionAllValue输出结果为-------------------
class java.lang.Integer---maxInactiveInterval---1800
class java.lang.Long---lastAccessedTime---1558785214274
class java.lang.String---sessionAttr:K1---V1
class java.awt.Point---sessionAttr:point---java.awt.Point[x=39,y=19]
class java.lang.Long---creationTime---1558783975274
-----------------------testSessionAllValue输出结果为-------------------
说明:本例中获取到了session ID中的所有数据信息,与上图Redis命令中获取的一致,不同的是他们的数据已经被反序列化(解码)出来了,比如默认的session有效时常为1800秒,K1与point的具体值。
(3)测试某个session ID的所有Key值,循环单个调用
//测试反序列化某个session ID的所有数据及类型,循环获取数据方式
@Test
public void testSessionIdJDKSerializer() throws Exception {
String sessionId = "spring:session:sessions:" + ID;
Map<String, String> sessions = jedis.hgetAll(sessionId);
Set<String> entrySet = sessions.keySet();
JdkSerializationRedisSerializer jdk = new JdkSerializationRedisSerializer();
for (String key : entrySet) {
byte bytes[] = jedis.hget(sessionId.getBytes() , key.getBytes());
Object value = jdk.deserialize(bytes);
System.out.println(value.getClass() + "--" + key + "--" + value);
}
}
说明:输出与上面一致,此处为循环调用的方式,意在介绍API。顺便介绍几个byte[]类型数据被反序列化的工具类:org.apache.commons.lang3.SerializationUtils、com.baomidou.mybatisplus.core.toolkit.SerializationUtils、org.springframework.util.SerializationUtils。
(1)Java序列化是啥别不知道,简单说就是将Java提供的一种对象字节存储方式;
(2)Java序列化对象需要实现Serializable接口,本例中的java.awt.Point对象已实现;
https://gitee.com/88911006/chendd-examples
点赞