摘要:是框架對的默認集成,我們在實際項目中,也經常使用它的去操作,一般來說沒什么問題,但是細心一點的同學會發現,經過這種方法寫入的數據會出現亂碼問題問題復現項目依賴配置文件配置配置類注入設置數據存入的序列化方式實例化對象可以
org.springframework.data.redis是Spring框架對Redis的默認集成,我們在實際項目中,也經常使用它的RedisTemplate去操作Redis,一般來說沒什么問題,但是細心一點的同學會發現,經過這種方法寫入redis的數據會出現亂碼問題問題復現 項目依賴
Redis配置org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-redis
yaml文件配置
spring: application: name: booklet-redis redis: host: 127.0.0.1 port: 6379 password: adminadmin timeout: 5000ms
Redis配置類
package com.liumapp.booklet.redis.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.*; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { /** * 注入 RedisConnectionFactory */ @Autowired RedisConnectionFactory redisConnectionFactory; @Bean public RedisTemplate測試代碼functionDomainRedisTemplate() { RedisTemplate redisTemplate = new RedisTemplate<>(); initDomainRedisTemplate(redisTemplate, redisConnectionFactory); return redisTemplate; } /** * 設置數據存入 redis 的序列化方式 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) { redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setConnectionFactory(factory); } /** * 實例化 HashOperations 對象,可以使用 Hash 類型操作 * * @param redisTemplate * @return */ @Bean public HashOperations hashOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForHash(); } /** * 實例化 ValueOperations 對象,可以使用 String 操作 * * @param redisTemplate * @return */ @Bean public ValueOperations valueOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForValue(); } /** * 實例化 ListOperations 對象,可以使用 List 操作 * * @param redisTemplate * @return */ @Bean public ListOperations listOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForList(); } /** * 實例化 SetOperations 對象,可以使用 Set 操作 * * @param redisTemplate * @return */ @Bean public SetOperations setOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForSet(); } /** * 實例化 ZSetOperations 對象,可以使用 ZSet 操作 * * @param redisTemplate * @return */ @Bean public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { return redisTemplate.opsForZSet(); } }
package com.liumapp.booklet.redis; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.ListOperations; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; @SpringBootTest(classes = BookletRedisMain.class) @RunWith(SpringRunner.class) public class BookletRedisMainTest { @Resource private ListOperationslistOperations; @Test public void leftPushTest () { List list = new ArrayList<>(); list.add("hello world"); listOperations.leftPush("listKey", list); } }
運行上述測試代碼后,我們會在redis中插入一組list類型的數據,其key為listKey,value為只有一個元素的list對象
接下來我們通過redis-cli去獲取listKey這個值,可以看到亂碼的出現:
127.0.0.1:6379> LRANGE listKey 0 10 1) "xacxedx00x05srx00x13java.util.ArrayListxx81xd2x1dx99xc7ax9dx03x00x01Ix00x04sizexpx00x00x00x01wx04x00x00x00x01tx00x0bhello worldx"
當然,這對于我們項目的實際使用沒有什么影響,在程序中再次獲取listKey也不會出現亂碼,只有通過redis-cli等工具直接取值的時候,才會出現亂碼
問題出現原因問題原因在于我們對Redis進行配置的這一段代碼(事實上這也是redisTemplate的默認配置代碼):
private void initDomainRedisTemplate(RedisTemplateredisTemplate, RedisConnectionFactory factory) { redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setConnectionFactory(factory); }
在這里,redisTemplate對HashValue和Value的序列化類采用的是JDK默認的序列化策略,而不是String類型的序列化策略,所以我們在redis-cli中看到的value會因為序列化策略的問題,出現亂碼
解決辦法將JDK默認的序列化策略更換為String類型的序列化策略
redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer());
但是這樣做的話,我們在進行存儲的時候,也只能存儲String類型的數據,所以測試代碼要進行如下修改
@Test public void leftPushTest () { Listlist = new ArrayList<>(); list.add("hello world2"); listOperations.leftPush("listKey", list.toString()); }
再一次去redis-cli中取值,得到如下結果:
127.0.0.1:6379> LRANGE listKey 0 10 1) "[hello world2]" 2) "xacxedx00x05srx00x13java.util.ArrayListxx81xd2x1dx99xc7ax9dx03x00x01Ix00x04sizexpx00x00x00x01wx04x00x00x00x01tx00x0bhello worldx"
可以發現亂碼問題已經解決
總結不建議更換redisTemplate默認的序列化策略,有亂碼就讓它亂著吧,反正知道正確的解碼策略就不會影響程序的正常運行(不過通過php等其他語言去獲取redis的值貌似不太好解決)
如果一定要更換策略,那么前往要注意,存儲數據的類型要根據所選擇的序列化策略去進行切換
項目案例源代碼:github/booklet-redis
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75877.html
摘要:爬蟲數據寫入文件中文亂碼,用在中打開文件沒有問題,但是用打開卻出現了問題,以下為解決方法。 python爬蟲數據寫入csv文件中文亂碼,用’utf-8‘在pycharm中打開文件沒有問題,但是用excel打開卻出現了問題,以下為解決方法。 (最近在練習爬蟲,這個博文是對自己學習的記錄和分享,...
閱讀 2053·2021-11-11 16:55
閱讀 1395·2021-09-28 09:36
閱讀 1038·2019-08-29 15:21
閱讀 1572·2019-08-29 14:10
閱讀 2757·2019-08-29 14:08
閱讀 1628·2019-08-29 12:31
閱讀 3243·2019-08-29 12:31
閱讀 976·2019-08-26 16:47