網站首頁 編程語言 正文
這里說的是Spring Data Redis(一下簡稱SDR)設置Hash存儲的序列化。
SDR序列化方式有多種
如:
StringRedisSerializer
JdkSerializationRedisSerializer
Jackson2JsonRedisSerializer
OxmSerializer
- 等等
目前我有個需求,是將數據用hash的形式存到Redis數據庫中,在網上搜了下實現方式,部分代碼如下:
@Bean public RedisTemplate<String,Object> redisTemplate(){ RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); initDomainRedisTemplate(redisTemplate, redisConnectionFactory); return redisTemplate; } /** * 設置數據存入 redis 的序列化方式 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate<String, Object> 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<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForHash(); }
對Redis的存儲設置是我自己寫的
/** * 添加 * * @param key key * @param filed filed * @param domain 對象 */ public void hset(String key,String filed,Object domain){ System.out.println("開始使用filed設置"); hashOperations.put(key, filed, domain); } /** * 查詢 * * @param key 查詢的key * @param field 查詢的field * @return */ public Object hget(String key,String field) { return hashOperations.get(key, field); }
方法:
@RequestMapping("/mytest") public Object myTest() { redisUtils.hset("mykey","myfield","myvalue"); return redisUtils.hget("mykey","myfield"); }
Hash的存儲跟String有些不同,從表面上看Hash多了個field,這個自己稍微想下就可以理解了。
執行上面的代碼后,用客戶端查看所存儲的值:
上圖顯示的是亂碼。
用redis-cli查看:
這里顯示的是我存的值myvalue前多了些東西,這是序列化的時候所加的一些東西。
執行方法時前端得到的值:
這里可見從redis中取出的值是跟我存入的完全一樣的(這是因為取出的時候Spring有做反序列化處理)。
如果從redis-cli中直接存儲:
host:6379> hset mykey2 myfield2 myvalue2 (integer) 1 host:6379> hget mykey2 myfield2 "myvalue2"
查看客戶端中的值:
在這里存入的hash顯示的是正常的。
所以我猜測之前redis桌面客戶端顯示“不正常”的原因應該是出在序列化的時候。
更改序列化方法
改為StringRedisSerializer方式(一般key都是字符串,所以繼續使用StringRedisSerializer,這里把Hash的value序列化改為StringRedisSerializer):
/** * 設置數據存入 redis 的序列化方式 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) { redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setConnectionFactory(factory); }
查看客戶端的值:
這時顯示OK了,redis-cli中顯示的也是OK的。
所以,我們遇到的問題貌似解決了。
因為我要存儲的是hash,而hashOperations為我們提供了另外一個方法putAll,這個方法支持對HashMap的操作。
代碼:
/** * 添加 * * @param key key * @param hm 要存入的hash表 */ public void hset(String key, HashMap<String,Object> hm){ System.out.println("開始使用hashmap設置"); hashOperations.putAll(key,hm); }
因為我的hashmap中要存的值包含時間,所以就要把值設為Object,代碼:
@RequestMapping("/hm") public void hmsetTest() { HashMap<String,Object> hm =new HashMap<String,Object>(); hm.put("myFieldKey","myFieldKey"); hm.put("createTime",new Date()); redisUtils.hset("mykey",hm); }
執行結果:
這時在調用的時候直接報錯了,說是Date類型無法轉String。
回到單個值存入的方法上:
public void hset(String key,String filed,Object domain){ System.out.println("開始使用filed設置"); hashOperations.put(key, filed, domain); }
用這里執行Date的存儲,結果還是包這個異常。
由此可見,使用StringRedisSerializer序列化并不能解決我們的問題,而且還有使用的限制。OxmSerializer這個東西我不太熟悉,所以沒有測試。
使用Jackson2JsonRedisSerializer
更改序列化方式
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
執行單個日期操作結果如下:
這里顯示的日期被轉成時間戳形式存儲的。
執行hashmap:
結果顯示執行的也是成功的,如果跟StringRedisSerializer比較會發現,存儲字符串的時候值得最外層會被加上“”。
繼續使用JdkSerializationRedisSerializer
可以正常存儲,但是顯示形式一樣不是我們期望的。
對于這個問題我網上有種解決方法,在redis-cli中查看的時候使用–raw指令
即啟動指令為:redis-cli –raw。這種方式也可以正常的查看中文。但是查看的時候日期依然有問題,而且字符串前邊會多些東西(t)。
OxmSerializer這個東西我不熟悉,所以就沒有測試,但是網上一般都說建議使用JdkSerializationRedisSerializer,而且這種效率是最高的,沒辦法,畢竟是原生的。
原文鏈接:https://blog.csdn.net/qq_35981283/article/details/71410479
相關推薦
- 2022-05-17 ubuntu下安裝go語言SDK
- 2022-11-04 C++淺析內存分區模型概念與示例_C 語言
- 2022-06-19 WPF項目在設計界面調用后臺代碼_實用技巧
- 2022-09-18 Go語言包管理工具Godep的用法_Golang
- 2022-07-30 SpringBoot的數據校驗(@Validated注解)、關于validation無法導入的問題解
- 2022-04-11 css實現左邊div固定寬度,右邊div自適應撐滿剩下的寬度
- 2022-12-11 教你使用MongoDB導入導出備份數據_MongoDB
- 2022-04-17 彈性布局 怎么讓某一列自適應元素內容的寬度
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支