RedisTemplate集成+封裝RedisUtil過(guò)程
1.項(xiàng)目搭建
創(chuàng)建一個(gè)redis模塊
調(diào)整pom.xml,使其成為單獨(dú)的模塊
- sun-common-redis的pom.xml 取消parent
- sun-common的pom.xml 取消對(duì)redis模塊的管理
- sun-frame的pom.xml 增加對(duì)redis模塊的管理
關(guān)于只在modules中配置子模塊,但是子模塊沒(méi)有配置parent的用處
1. 多模塊項(xiàng)目的構(gòu)建管理
使用標(biāo)簽可以將多個(gè)子模塊組織在一個(gè)頂層的父項(xiàng)目中,從而實(shí)現(xiàn)以下幾個(gè)目標(biāo):
- a. 單點(diǎn)構(gòu)建
- 你可以在父項(xiàng)目的根目錄下運(yùn)行一次mvn install命令,就可以構(gòu)建和安裝所有子模塊到本地Maven倉(cāng)庫(kù),而不需要分別進(jìn)入每個(gè)子模塊目錄單獨(dú)運(yùn)行構(gòu)建命令。這大大簡(jiǎn)化了多模塊項(xiàng)目的構(gòu)建過(guò)程。
- b. 構(gòu)建順序管理
- Maven會(huì)根據(jù)模塊間的依賴關(guān)系,自動(dòng)確定各個(gè)模塊的構(gòu)建順序,確保在構(gòu)建一個(gè)模塊之前,先構(gòu)建它所依賴的模塊。這在多模塊項(xiàng)目中是非常有用的,可以避免手動(dòng)管理依賴順序的麻煩。
2. 統(tǒng)一的版本管理
即使子模塊沒(méi)有指定父項(xiàng)目,使用標(biāo)簽仍然可以幫助你管理各個(gè)子模塊的版本一致性。你可以在父項(xiàng)目的POM文件中統(tǒng)一指定各個(gè)子模塊的版本號(hào),然后在每個(gè)子模塊的POM文件中引用這個(gè)版本號(hào)。
3. 項(xiàng)目結(jié)構(gòu)的組織和清晰度
將多個(gè)子模塊組織在一個(gè)父項(xiàng)目中,可以使項(xiàng)目結(jié)構(gòu)更加清晰,便于管理。通過(guò)標(biāo)簽,你可以一目了然地看到項(xiàng)目中包含哪些子模塊,以及它們之間的組織結(jié)構(gòu)。
sun-common-redis引入redis依賴
<dependencies> <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.4.2</version> </dependency> <!-- redis的pool --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.9.0</version> </dependency> </dependencies>
2.sun-user集成RedisTemplate
pom.xml引入sun-common-redis
<!-- 引入sun-common-redis --> <dependency> <groupId>com.sunxiansheng</groupId> <artifactId>sun-common-redis</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
application.yml配置redis(集群模式)
spring: # 配置redis(集群模式) redis: password: # Redis服務(wù)器密碼 database: 0 # 默認(rèn)數(shù)據(jù)庫(kù)為0號(hào) timeout: 10000ms # 連接超時(shí)時(shí)間是10000毫秒 lettuce: pool: max-active: 8 # 最大活躍連接數(shù),使用負(fù)值表示沒(méi)有限制,最佳配置為核數(shù)*2 max-wait: 10000ms # 最大等待時(shí)間,單位為毫秒,使用負(fù)值表示沒(méi)有限制,這里設(shè)置為10秒 max-idle: 200 # 最大空閑連接數(shù) min-idle: 5 # 最小空閑連接數(shù) cluster: nodes:
TestController.java測(cè)試RedisTemplate
代碼
package com.sunxiansheng.user.controller; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * Description: * @Author sun * @Create 2024/7/8 17:55 * @Version 1.0 */ @RestController public class TestController { @Resource private RedisTemplate redisTemplate; @RequestMapping("/testRedis") public String testRedis() { redisTemplate.opsForValue().set("name", "sunxiansheng"); return "Hello World!"; } }
訪問(wèn)測(cè)試(發(fā)現(xiàn)有亂碼)
重寫RedisTemlate
引入Jackson的依賴
<!-- 重寫RedisTemlate需要的jackson序列化工具 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.4</version> </dependency>
RedisConfig.java
package com.sunxiansheng.redis.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; 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.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Description: RedisConfig配置類 * @Author sun * @Create 2024/7/19 11:11 * @Version 1.0 */ @Configuration public class RedisConfig { /** * 重寫RedisTemplate 解決亂碼問(wèn)題 * * @param redisConnectionFactory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // key就使用redis提供的序列化RedisSerializer即可 RedisSerializer<String> redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); // value要使用Jackson的序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer()); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer()); return redisTemplate; } /** * 獲取一個(gè)Jackson的序列化對(duì)象邏輯 * * @return */ private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() { // 創(chuàng)建一個(gè)Jackson2JsonRedisSerializer對(duì)象,用于序列化和反序列化Java對(duì)象 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); // 創(chuàng)建一個(gè)ObjectMapper對(duì)象,用于JSON序列化和反序列化的配置 ObjectMapper objectMapper = new ObjectMapper(); // 設(shè)置ObjectMapper的可見(jiàn)性,使其可以訪問(wèn)所有屬性 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 配置ObjectMapper,使其在遇到未知屬性時(shí)不會(huì)拋出異常 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 將配置好的ObjectMapper設(shè)置到Jackson2JsonRedisSerializer中 jackson2JsonRedisSerializer.setObjectMapper(objectMapper); // 返回配置好的Jackson2JsonRedisSerializer對(duì)象 return jackson2JsonRedisSerializer; } }
測(cè)試
3.封裝RedisUtil
RedisUtil.java
package com.sunxiansheng.redis.util; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Description: RedisUtil工具類 * @Author sun * @Create 2024/6/5 14:17 * @Version 1.0 */ @Component public class RedisUtil { @Resource private RedisTemplate redisTemplate; private static final String CACHE_KEY_SEPARATOR = "."; /** * 構(gòu)建緩存key * @param strObjs 多個(gè)字符串拼接成緩存key * @return 拼接后的緩存key */ public String buildKey(String... strObjs) { return Stream.of(strObjs).collect(Collectors.joining(CACHE_KEY_SEPARATOR)); } /** * 是否存在key * @param key Redis中的key * @return true如果key存在,否則false */ public boolean exist(String key) { return redisTemplate.hasKey(key); } /** * 刪除key * @param key Redis中的key * @return true如果刪除成功,否則false */ public boolean del(String key) { return redisTemplate.delete(key); } /** * 設(shè)置key-value對(duì) * @param key Redis中的key * @param value 要設(shè)置的值 */ public void set(String key, String value) { redisTemplate.opsForValue().set(key, value); } /** * 設(shè)置key-value對(duì),如果key不存在,則設(shè)置成功,并指定過(guò)期時(shí)間 * @param key Redis中的key * @param value 要設(shè)置的值 * @param time 過(guò)期時(shí)間 * @param timeUnit 時(shí)間單位 * @return true如果設(shè)置成功,否則false */ public boolean setNx(String key, String value, Long time, TimeUnit timeUnit) { return redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit); } /** * 獲取指定key的值 * @param key Redis中的key * @return key對(duì)應(yīng)的值 */ public String get(String key) { return (String) redisTemplate.opsForValue().get(key); } /** * 向有序集合中添加元素 * @param key Redis中的key * @param value 元素的值 * @param score 元素的分?jǐn)?shù) * @return true如果添加成功,否則false */ public Boolean zAdd(String key, String value, Long score) { return redisTemplate.opsForZSet().add(key, value, Double.valueOf(String.valueOf(score))); } /** * 獲取有序集合的元素?cái)?shù)量 * @param key Redis中的key * @return 元素?cái)?shù)量 */ public Long countZset(String key) { return redisTemplate.opsForZSet().size(key); } /** * 獲取有序集合指定范圍內(nèi)的元素 * @param key Redis中的key * @param start 起始位置 * @param end 結(jié)束位置 * @return 指定范圍內(nèi)的元素集合 */ public Set<String> rangeZset(String key, long start, long end) { return redisTemplate.opsForZSet().range(key, start, end); } /** * 刪除有序集合中的指定元素 * @param key Redis中的key * @param value 要?jiǎng)h除的元素 * @return 被刪除的元素?cái)?shù)量 */ public Long removeZset(String key, Object value) { return redisTemplate.opsForZSet().remove(key, value); } /** * 刪除有序集合中的多個(gè)元素 * @param key Redis中的key * @param value 要?jiǎng)h除的元素集合 */ public void removeZsetList(String key, Set<String> value) { value.forEach(val -> redisTemplate.opsForZSet().remove(key, val)); } /** * 獲取有序集合中指定元素的分?jǐn)?shù) * @param key Redis中的key * @param value 元素的值 * @return 元素的分?jǐn)?shù) */ public Double score(String key, Object value) { return redisTemplate.opsForZSet().score(key, value); } /** * 獲取有序集合中指定分?jǐn)?shù)范圍內(nèi)的元素 * @param key Redis中的key * @param start 起始分?jǐn)?shù) * @param end 結(jié)束分?jǐn)?shù) * @return 指定分?jǐn)?shù)范圍內(nèi)的元素集合 */ public Set<String> rangeByScore(String key, long start, long end) { return redisTemplate.opsForZSet().rangeByScore(key, Double.valueOf(String.valueOf(start)), Double.valueOf(String.valueOf(end))); } /** * 增加有序集合中指定元素的分?jǐn)?shù) * @param key Redis中的key * @param obj 元素的值 * @param score 增加的分?jǐn)?shù) * @return 增加后的分?jǐn)?shù) */ public Object addScore(String key, Object obj, double score) { return redisTemplate.opsForZSet().incrementScore(key, obj, score); } /** * 獲取有序集合中指定元素的排名 * @param key Redis中的key * @param obj 元素的值 * @return 元素的排名 */ public Object rank(String key, Object obj) { return redisTemplate.opsForZSet().rank(key, obj); } /** * 從 Redis 有序集合(Sorted Set)中按分?jǐn)?shù)范圍獲取成員及其分?jǐn)?shù) * @param key 排行榜的key * @param start 起始位置(包含) * @param end 結(jié)束位置(包含) * @return Set<ZSetOperations.TypedTuple<String>> : 每個(gè) TypedTuple 對(duì)象包含以下內(nèi)容:value: 集合中的成員,score: 成員的分?jǐn)?shù)。 */ public Set<ZSetOperations.TypedTuple<String>> rankWithScore(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end); } /** * 向Redis中的hash結(jié)構(gòu)存儲(chǔ)數(shù)據(jù) * @param key 一個(gè)hash結(jié)構(gòu)的key * @param hashKey hash中的小key * @param hashVal hash中的小value */ public void putHash(String key, String hashKey, Object hashVal) { redisTemplate.opsForHash().put(key, hashKey, hashVal); } /** * Redis中的String類型,獲取value時(shí)將其轉(zhuǎn)換為int類型 * @param key Redis中的key * @return key對(duì)應(yīng)的整數(shù)值 */ public Integer getInt(String key) { return (Integer) redisTemplate.opsForValue().get(key); } /** * Redis中的String類型,將value增加一 * @param key Redis中的key * @param count 增加的數(shù)量 */ public void increment(String key, Integer count) { redisTemplate.opsForValue().increment(key, count); } /** * Redis中的hash類型,根據(jù)key來(lái)將每一個(gè)hashKey和hashValue轉(zhuǎn)換為Map類型 * @param key Redis中的hash結(jié)構(gòu)的key * @return Map<Object, Object> 包含hash結(jié)構(gòu)中的所有鍵值對(duì) */ public Map<Object, Object> getHashAndDelete(String key) { Map<Object, Object> map = new HashMap<>(); // 掃描hash,指定每一個(gè)Entry的類型,這里返回的就是Map的游標(biāo),可以進(jìn)行遍歷 Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(key, ScanOptions.NONE); // 遍歷每一條數(shù)據(jù),放到map中 while (cursor.hasNext()) { Map.Entry<Object, Object> next = cursor.next(); Object hashKey = next.getKey(); Object hashValue = next.getValue(); map.put(hashKey, hashValue); // 每遍歷一條就刪除 redisTemplate.opsForHash().delete(key, hashKey); } return map; } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis sentinel節(jié)點(diǎn)如何修改密碼
這篇文章主要介紹了Redis sentinel節(jié)點(diǎn)如何修改密碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01redis實(shí)現(xiàn)sentinel哨兵架構(gòu)的方法
哨兵是一個(gè)分布式系統(tǒng),可以在一個(gè)架構(gòu)中運(yùn)行多個(gè)哨兵(sentinel) 進(jìn)程,這些進(jìn)程使用流言協(xié)議(gossip protocols)來(lái)接收關(guān)于Master主服務(wù)器是否下線的信息,這篇文章主要介紹了redis實(shí)現(xiàn)sentinel哨兵架構(gòu),需要的朋友可以參考下2022-11-11odoo中使用redis實(shí)現(xiàn)緩存的步驟
這篇文章主要介紹了odoo中使用redis實(shí)現(xiàn)緩存的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04NestJS+Redis實(shí)現(xiàn)手寫一個(gè)限流器
限流是大型系統(tǒng)必備的保護(hù)措施,本文將結(jié)合redis , lua 腳本 以及 Nestjs Guard 來(lái)實(shí)現(xiàn) 限流的效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11Redis緩存lettuce更換為Jedis的實(shí)現(xiàn)步驟
在springboot中引入spring-boot-starter-data-redis依賴時(shí),默認(rèn)使用的是lettuce,如果不想使用lettuce而是使用Jedis連接池,本文主要介紹了Redis緩存lettuce更換為Jedis的實(shí)現(xiàn)步驟,感興趣的可以了解一下2024-08-08Redis 的查詢很快的原因解析及Redis 如何保證查詢的高效
由于redis是內(nèi)存數(shù)據(jù)庫(kù),歸功于它的數(shù)據(jù)結(jié)構(gòu)所以查詢效率非常高,今天通過(guò)本文給大家介紹下Redis 的查詢很快的原因解析及Redis 如何保證查詢的高效,感興趣的朋友一起看看吧2022-03-03實(shí)現(xiàn)在線?+?離線模式進(jìn)行遷移?Redis?數(shù)據(jù)實(shí)戰(zhàn)指南
這篇文章主要介紹了實(shí)現(xiàn)在線?+?離線模式進(jìn)行遷移?Redis?數(shù)據(jù)實(shí)戰(zhàn)指南的相關(guān)資料,需要的朋友可以參考下2023-01-01