springboot集成redis序列化的问题

Posted 张and强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot集成redis序列化的问题相关的知识,希望对你有一定的参考价值。

springboot集成redis序列化的问题

在springboot中RedisTemplate默认使用的是Java本地的序列化(JdkSerializationRedisSerializer)方式

public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }

        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }

        this.initialized = true;
    }

也去看了一下官方文档(https://docs.spring.io/spring-data/redis/docs/2.3.1.RELEASE/reference/html/#redis:serializer),里面写到建议转成JSON格式,如下图所示

![image-20200722160753602](

使用默认的序列化方式返回的结果会包含类的信息:

Book(id=1, name=情人, price=0.0, author=jack)
从redis-cli查询:
127.0.0.1:6379> get book:2
"\\xac\\xed\\x00\\x05sr\\x00 com.jack.springbootlearn.bo.Book/\\xe3IUI\\xb5\\xab\\xf4\\x02\\x00\\x04J\\x00\\x02idD\\x00\\x05priceL\\x00\\x06authort\\x00\\x12Ljava/lang/String;L\\x00\\x04nameq\\x00~\\x00\\x01xp\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00t\\x00\\x04jackt\\x00\\x06\\xe6\\x83\\x85\\xe4\\xba\\xba"

使用Jackson2JsonRedisSerializer序列化结果:

{id=1, name=情人, price=0.0, author=jack}
从redis-cli中查询:
"{\\"id\\":1,\\"name\\":\\"\\xe6\\x83\\x85\\xe4\\xba\\xba\\",\\"price\\":0.0,\\"author\\":\\"jack\\"}"

具体代码实现:

配置类

/**
* @Description:    
* @Author:         ZhangQiang
* @CreateDate:     2020/7/8 16:24
*/
@Configuration
public class RedisConfig {
	@Bean
	public RedisTemplate<String,Object> getRedisTemplate(RedisConnectionFactory redisConnectionFactory){
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(serializer()));
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		redisTemplate.setHashValueSerializer(serializer());
		redisTemplate.afterPropertiesSet();
		return redisTemplate;
	}

	private Jackson2JsonRedisSerializer<Object> serializer() {
		// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();

		// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

		// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
		objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

		jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
		return jackson2JsonRedisSerializer;
	}

}

redis工具类

@Component
public class RedisUtil {

	@Autowired
	private RedisTemplate<String,Object> redisTemplate;

	/**
	 * String类型
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(String key,Object value){
		boolean result = false;
		try {
			ValueOperations operations = redisTemplate.opsForValue();
			operations.set(key,value);
			result = true;
		}catch (Exception e){
			System.out.println(e.getMessage());
		}
		return result;
	}

	/**
	 * Strin类型设置过期时间
	 * @param key
	 * @param value
	 * @param expireTime
	 * @return
	 */
	public boolean set(String key,Object value,long expireTime){
		boolean result = false;
		try {
			ValueOperations operations = redisTemplate.opsForValue();
			operations.set(key,value,expireTime);
			result = true;
		}catch (Exception e){
			System.out.println(e.getMessage());
		}
		return result;
	}

	public String get(String key){
		ValueOperations<String, Object> stringObjectValueOperations = redisTemplate.opsForValue();
		Object o = stringObjectValueOperations.get(key);
		return o.toString();
	}

测试类

@SpringBootTest
public class RedisTest {

	@Autowired
	private RedisUtil redisUtil;

	@Test
	public void setTest(){
		Book book = new Book();
		book.setName("情人");
		book.setId(1);
		book.setAuthor("jack");
		redisUtil.set("book:2",book);
	}
	@Test
	public void get(){
		String s = redisUtil.get("book:1");
		System.out.println(s);
		/*String s1 = redisUtil.get("book:2");
		System.out.println(s1);*/
	}

}

以上是关于springboot集成redis序列化的问题的主要内容,如果未能解决你的问题,请参考以下文章

Springboot学习SpringBoot集成Shiro前后端分离使用redis做缓存个人博客搭建

SpringBoot教程(十四) | SpringBoot集成Redis(全网最全)

Spring boot集成Redis—进行增加,更新,查询,批量删除等操作

springboot集成springsession利用redis来实现session共享

SpringBoot集成redis的LBS功能

Springboot集成Redis详细教程(缓存注解使用@Cacheable,@CacheEvict,@CachePut)