1. 程式人生 > 實用技巧 >springboot整合redis序列化的問題

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);*/
	}

}