Spring Session Redis最佳实践(二)Redis中的数据存储

Spring Session
placeholder image
admin 发布于:2019-05-25 19:04:03
阅读:loading

前一文我通过一些示例实践实现了一个较为简单的Spring Session Redis的数据管理,本篇主要说一下Session数据存储在Redis中的数据结构及使用Jedis进行一些小小的Junit测试一下,将存储至Redis中的数据读取出来,通过读取后的数据结构来了解它的存储。

Session序列化存储背景

对于JDBC存储至表中的Session数据我们易于管理,直接通过查询表数据的方式即可,但存储至Redis中的Session数据存储,我也是耗费了许久时间才略有一些浅浅的总结,如果你有注意到前篇文章中的一些Redis数据查看命令与截图,兴许就有此一问,这里面的数据都是啥啊,看不懂是正常的,这说明Redis中存储的Session数据默认是采用JDK自带的序列化存储的,界面上看到的session数据都是从Redis中获取出来,并且通过JDK的反序列化解出来显示的,下面专门针对于一个session ID与session中存储的数据(包含字符串类型值与Java对象类型),去了解它的序列化存储,参考Session ID与Session中存储的数据截图如下:

image.png

Redis中查看这个session ID中存储的数据结构图,可以看出奇数行号的为session数据对象的属性,带sessionAttr开头的则为session中存储的参数信息,sessionAttr:K1为字符串类型,sessionAttr:point存储的为java.awt.Point类型的对象,但是实际上的数值(偶数行)则无法识别了,参考如下图:

image.png

Jedis的API与反序列化

通过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


 点赞


 发表评论

当前回复:作者

 评论列表


留言区