Spring Session Redis最佳实践(2)认识Redis中的数据存储

欢迎转至站内查看原文,链接为:https://www.chendd.cn/information/viewInformation/experienceShare/310.a

前一文我通过一些示例实践实现了一个较为简单的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中存储的数据截图如下:

blob.png

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

blob.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。

其它说明

(1)Java序列化是啥别不知道,简单说就是将Java提供的一种对象字节存储方式;

(2)Java序列化对象需要实现Serializable接口,本例中的java.awt.Point对象已实现;

源码下载

https://gitee.com/88911006/chendd-examples

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值