前言

由于Springboot默认提供了序列化方式并不是非常理想,对于高要求的情况下,序列化的速度和序列化之后大小有要求的情况下,不能满足,所以可能需要更换序列化的方式。
这里主要记录更换序列化的方式以及其中一些出现问题。
坑坑坑坑坑坑!!!
这次踩的坑坑。

序列化方式更换

第一步,加入依赖

//protostuff序列化依赖
compile group: 'io.protostuff', name: 'protostuff-runtime', version: '1.6.0'
compile group: 'io.protostuff', name: 'protostuff-core', version: '1.6.0'

第二步,加入序列化工具

  1. import io.protostuff.LinkedBuffer;
  2. import io.protostuff.ProtostuffIOUtil;
  3. import io.protostuff.Schema;
  4. import io.protostuff.runtime.RuntimeSchema;
  5. import org.springframework.data.redis.serializer.RedisSerializer;
  6. import org.springframework.data.redis.serializer.SerializationException;
  7.  
  8. /**
  9. * ProtoStuff序列化工具
  10. * @author LinkinStar
  11. */
  12. public class ProtostuffSerializer implements RedisSerializer {
  13.  
  14. private boolean isEmpty(byte[] data) {
  15. return (data == null || data.length == 0);
  16. }
  17.  
  18. private final Schema<ProtoWrapper> schema;
  19.  
  20. private final ProtoWrapper wrapper;
  21.  
  22. private final LinkedBuffer buffer;
  23.  
  24. public ProtostuffSerializer() {
  25. this.wrapper = new ProtoWrapper();
  26. this.schema = RuntimeSchema.getSchema(ProtoWrapper.class);
  27. this.buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
  28. }
  29.  
  30. @Override
  31. public byte[] serialize(Object t) throws SerializationException {
  32. if (t == null) {
  33. return new byte[0];
  34. }
  35. wrapper.data = t;
  36. try {
  37. return ProtostuffIOUtil.toByteArray(wrapper, schema, buffer);
  38. } finally {
  39. buffer.clear();
  40. }
  41. }
  42.  
  43. @Override
  44. public T deserialize(byte[] bytes) throws SerializationException {
  45. if (isEmpty(bytes)) {
  46. return null;
  47. }
  48. ProtoWrapper newMessage = schema.newMessage();
  49. ProtostuffIOUtil.mergeFrom(bytes, newMessage, schema);
  50. return (T) newMessage.data;
  51. }
  52.  
  53. private static class ProtoWrapper {
  54. private Object data;
  55. }
  56. }

第三步,对RedisTemplate进行封装

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.data.redis.core.RedisTemplate;
  4. import org.springframework.stereotype.Component;
  5.  
  6. import java.util.concurrent.TimeUnit;
  7.  
  8. /**
  9. * Redis操作工具类
  10. * @author LinkinStar
  11. */
  12. @Component
  13. public class RedisUtil {
  14.  
  15. @Autowired
  16. @Qualifier("protoStuffTemplate")
  17. private RedisTemplate protoStuffTemplate;
  18.  
  19. /**
  20. * 设置过期时间,单位秒
  21. * @param key 键的名称
  22. * @param timeout 过期时间
  23. * @return 成功:true,失败:false
  24. */
  25. public boolean setExpireTime(String key, long timeout) {
  26. return protoStuffTemplate.expire(key, timeout, TimeUnit.SECONDS);
  27. }
  28.  
  29. /**
  30. * 通过键删除一个值
  31. * @param key 键的名称
  32. */
  33. public void delete(String key) {
  34. protoStuffTemplate.delete(key);
  35. }
  36.  
  37. /**
  38. * 判断key是否存在
  39. * @param key 键的名称
  40. * @return 存在:true,不存在:false
  41. */
  42. public boolean hasKey(String key) {
  43. return protoStuffTemplate.hasKey(key);
  44. }
  45.  
  46. /**
  47. * 数据存储
  48. * @param key 键
  49. * @param value 值
  50. */
  51. public void set(String key, Object value) {
  52. protoStuffTemplate.boundValueOps(key).set(value);
  53. }
  54.  
  55. /**
  56. * 数据存储的同时设置过期时间
  57. * @param key 键
  58. * @param value 值
  59. * @param expireTime 过期时间
  60. */
  61. public void set(String key, Object value, Long expireTime) {
  62. protoStuffTemplate.boundValueOps(key).set(value, expireTime, TimeUnit.SECONDS);
  63. }
  64.  
  65. /**
  66. * 数据取值
  67. * @param key 键
  68. * @return 查询成功:值,查询失败,null
  69. */
  70. public Object get(String key) {
  71. return protoStuffTemplate.boundValueOps(key).get();
  72. }
  73. }

第四步,修改默认序列化方式

  1. import com.linkinstars.springBootTemplate.util.ProtostuffSerializer;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.data.redis.connection.RedisConnectionFactory;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.data.redis.serializer.StringRedisSerializer;
  7. import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
  8.  
  9. /**
  10. * redisTemplate初始化,开启spring-session redis存储支持
  11. * @author LinkinStar
  12. */
  13. @Configuration
  14. @EnableRedisHttpSession
  15. public class RedisConfig {
  16.  
  17. /**
  18. * redisTemplate 序列化使用的Serializeable, 存储二进制字节码, 所以自定义序列化类
  19. * @Rparam redisConnectionFactory
  20. * @return redisTemplate
  21. */
  22. @Bean
  23. public RedisTemplate<Object, Object> protoStuffTemplate(RedisConnectionFactory redisConnectionFactory) {
  24. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  25. template.setConnectionFactory(redisConnectionFactory);
  26.  
  27. // redis value使用的序列化器
  28. template.setValueSerializer(new ProtostuffSerializer());
  29. // redis key使用的序列化器
  30. template.setKeySerializer(new StringRedisSerializer());
  31.  
  32. template.afterPropertiesSet();
  33. return template;
  34. }
  35. }

第五步,相应测试

  1. //测试redis
  2. UserEntity user = new UserEntity();
  3. user.setId(1);
  4. user.setVal("xxx");
  5.  
  6. redisUtil.set("xxx", user);
  7. Object object = redisUtil.get("xxx");
  8. UserEntity userTemp = (UserEntity) object;
  9.  
  10. System.out.println("redis数据获取为: " + userTemp);
  11. redisUtil.delete("xxx");
  12. System.out.println("redis删除数据之后获取为: " + redisUtil.get("xxx"));

遇到问题

问题描述:序列化之后反序列化没有问题,但是强制转换成对应的类出现问题,抛出无法强制转换的异常。
问题分析:无法强制转换说明可能两个类的类加载器不一样,所以打印两者类加载器发现确实不一样。
发现其中一个类的类加载器出现了devtool的字样
所以联想到可能是热部署机制导致这样问题的产生。
然后查询网络资料,并在多台机器上进行测试,发现有的机器不会出现这样的问题,而有的机器就会出现。
如果使用Kryo进行序列化的话,第一次就会出现上述问题,而使用protostuff热部署之后才会出现上述问题。
问题解决:最后为了免除后续可能出现的问题,注释了热部署的devtool的相应依赖和相应的配置得以解决。

完整代码

github:https://github.com/LinkinStars/springBootTemplate

参考博客:
https://www.spldeolin.com/posts/redis-template-protostuff/
https://blog.csdn.net/wsywb111/article/details/79612081
https://github.com/protostuff/protostuff

SpringBoot修改Redis序列化方式的更多相关文章

  1. SpringBoot2.x修改Redis序列化方式

    添加一个配置类即可: /** * @Author FengZeng * @Date 2022-03-22 13:43 * @Description TODO */ @Configuration pub ...

  2. Redis 序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer

    当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的.RedisTemplate默认使用的是JdkSerializat ...

  3. SpringBoot中redis的使用介绍

    REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C语言编写.遵守B ...

  4. springBoot集成Redis,RedisTmple操作redis和注解实现添加和清空缓存功能

    配置 maven项目进入相关配置 <dependency>    <groupId>org.springframework.boot</groupId>    &l ...

  5. SpringBoot项目使用RedisTemplate设置序列化方式

    前端时间新项目使用SpringBoot的RedisTemplate遇到一个问题,先简单描述一下问题:不同项目之间redis共用一个,但是我们新项目读不到老项目存储的缓存.新项目搭建的时候没有跟老项目使 ...

  6. 【springBoot】springBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  7. SpringBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  8. Springboot+Redis序列化坑

    今天在测试springboot整合redis的时候遇到下面这个坑,百度来百度去发现提示都是ajax的问题,真的是醉了,错误提示如下所示,不信大家可以直接复制百度一下答案是什么(流泪中....),错误如 ...

  9. 三种序列化方式存取redis的方法

    常见的的序列化反序列方式的效率: protoBuf(PB) > fastjson > jackson > hessian > xstream > java 数据来自于:h ...

随机推荐

  1. vue中使用stylus

    1.创建完成一个初始项目后,通过 npm install stylus -D命令,在项目内安装stylus.(注意:命令结尾 -D 即是 --save-dev 的简写形式) 2.需要安装loader, ...

  2. sql server 关于日期格式转换查询备注

    select GETDATE()--2016-01-08 16:15:05.787select convert(varchar,getdate(),11)--16/01/08select conver ...

  3. css 制作导航条布局

    代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  4. entOS7查看开放端口命令

    CentOS7的开放关闭查看端口都是用防火墙来控制的,具体命令如下: 查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=/tc ...

  5. git教程——安装配置

    Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个 ...

  6. sql server创建登录出发器后导致登录失败--解决方案

    1.选择sql server配置管理器---sql server服务--右键属性--启动参数--添加-f.-m两个参数并重启sql server服务 2.重新启动sql server以windos身份 ...

  7. 用Group by分组后,取每组的前3条记录,怎么取?

    使用子查询进行查询 SELECT * FROM home_content a WHERE ( SELECT count(id) FROM home_content WHERE class_link = ...

  8. Redis安装、命令以及设置密码遇到的问题

    一.下载Redis 如果没有 安装wget先安装wget和gcc(使用make的时候会用上) wget http://download.redis.io/releases/redis-4.0.8.ta ...

  9. 常用的js效果

    使用jquery实现鼠标悬停显示层 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  10. 第一次app经验

    第一次做一个app 发现 需要和前端沟通好而且 还要注意细节  效果图细节不要忘记 尽量多穿数据不要少传数据 而且 对接 注意细节