【SpringBoot】結合Redis實現快取

陆陆无为而治者發表於2024-10-04

Redis經常用於快取。接下來,我們以Springboot框架為例。實現一些Redis的基礎操作,建立完SpingBoot專案後,具體步驟如下圖:

pom中新增專案依賴

<!-- Redis 快取-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.5.15</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.5.12</version>
</dependency>

配置Redis連線

開啟配置檔案(以application.yml為例)

spring:
  redis:
    database: 0     # 資料庫索引,預設為0
    host: 127.0.0.1 # redis地址
    port: 6379      # redis伺服器埠地址 
    # sping.redis.password 表示密碼,因為密碼為空,這裡不設定
    jedis:
      pool:
        max-wait: 3000  # 連線池最大阻塞等待時間,單位毫秒(使用負值表示沒有限制)
        min-idle: 0     # 連線池最小空閒時間
    timeout: 3000       # 連線超時時間(毫秒)

編寫Redis配置檔案

新建配置檔案。這裡實現了連線配置工廠和序列化。(需要序列化,否則儲存的中文,不可閱讀)

 1 @Configuration
 2 @EnableCaching
 3 public class RedisConfig extends CachingConfigurerSupport {
 4 
 5     /**
 6      * RedisTemplate相關配置
 7      * 使redis支援插入物件
 8      *
 9      * @param factory
10      * @return 方法快取 Methods the cache
11      */
12     @Bean
13     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
14         RedisTemplate<String, Object> template = new RedisTemplate<>();
15         // 配置連線工廠
16         template.setConnectionFactory(factory);
17         // 序列化 key 和hashKey採用String序列化;value和hashValue採用JSON序列化
18         GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
19         template.setKeySerializer(RedisSerializer.string());
20         template.setHashKeySerializer(RedisSerializer.string());
21         // value和hashvalue採用JSON序列化
22         template.setValueSerializer(jsonRedisSerializer);
23         template.setHashValueSerializer(jsonRedisSerializer);
24         return template;
25     }
26 }

測試Redis快取

寫入測試方法,發現能夠完成Redis的儲存與讀取。

 1 @SpringBootTest
 2 public class RedisTest {
 3     @Autowired
 4     private RedisTemplate redisTemplate;
 5     @Autowired
 6     private RedisUtils redisUtils;
 7     /**
 8      * 測試新增String型別
 9      * @author lyj
10      * @date 2024-09-28
11      */
12     @Test
13     public void testAddString(){
14         String key = "redisTest:user:name";
15         String value = "張三";
16         redisTemplate.opsForValue().set(key,value);
17         System.out.println(redisTemplate.opsForValue().get(key));
18     }
19     /**
20      * 測試新增Object型別
21      * @author lyj
22      * @date 2024-09-28
23      */
24     @Test
25     public void testAddObject(){
26         String key = "redisTest:user:1";
27         SysUser sysUser = new SysUser();
28         sysUser.setId(1);
29         sysUser.setUsername("林沖");
30         sysUser.setPassword("123456");
31         redisTemplate.opsForValue().set(key,sysUser);
32     }
33     
34     /**
35      * 測試讀取redis
36      * @author lyj
37      * @date 2024-09-28
38      */
39     @Test
40     public void testGet(){
41         String key = "redisTest:user:name";
42         System.out.println( redisTemplate.opsForValue().get(key));      // 張三
43     }
44 }

發現,能夠實現類的建立和讀取。

建立Redis快取工具類

上面案例都是直接用RedisTemplate操作Redis。我們可以實現,RedisUtils交給Spring容器例項化,使用時直接註解注入,使用方便簡單,減少使用難度。

  1 @Component
  2 public class RedisUtils {
  3     @Autowired
  4     private RedisTemplate redisTemplate;
  5 
  6     public RedisUtils(RedisTemplate redisTemplate) {
  7         this.redisTemplate = redisTemplate;
  8     }
  9     //region 基礎操作
 10     /**
 11      * 指定快取失效時間
 12      * @param key 鍵
 13      * @param time 時間(秒)
 14      * @return
 15      */
 16     public  boolean expire(String key,long time){
 17         try {
 18             if(time > 0){
 19                 redisTemplate.expire(key,time, TimeUnit.SECONDS);
 20             }
 21             return true;
 22         }catch (Exception e){
 23             e.printStackTrace();
 24             return false;
 25         }
 26     }
 27 
 28     /**
 29      * 根據可以獲取過期時間
 30      * @param key 鍵(不能為null)
 31      * @return 返回單位秒,返回 -1 代表永久有效
 32      */
 33     public long getExpire(String key){
 34         return  redisTemplate.getExpire(key,TimeUnit.SECONDS);
 35     }
 36 
 37     /**
 38      * 判斷key是否存在
 39      * @param key 鍵
 40      * @return
 41      */
 42     public boolean hasKey(String key){
 43         try{
 44             return redisTemplate.hasKey(key);
 45         }catch (Exception e){
 46             e.printStackTrace();
 47             return  false;
 48         }
 49     }
 50 
 51     /**
 52      * 刪除1個或多個快取
 53      * @param keys
 54      */
 55     public long del(String ...keys){
 56         if(keys != null && keys.length > 0){
 57             if(keys.length ==1){
 58                 return  redisTemplate.delete(keys[0]) ? 1L:0L;
 59             }else {
 60                return redisTemplate.delete(CollectionUtils.arrayToList(keys)) ;
 61             }
 62         }
 63         return  0L;
 64     }
 65 
 66     /**
 67      * 模糊查詢獲取key值
 68      * @param pattern
 69      * @return
 70      */
 71     public Set keys(String pattern){
 72         return  redisTemplate.keys(pattern);
 73     }
 74 
 75     /**
 76      * 使用redis的訊息佇列
 77      * @param channel
 78      * @param message 訊息內容
 79      */
 80     public  void  convertAndSend(String channel, Object message){
 81         redisTemplate.convertAndSend(channel,message);
 82     }
 83     //endregion
 84     //region String
 85 
 86     /**
 87      * 獲取普通快取獲取
 88      * @param key 鍵
 89      * @return 90      */
 91     public Object get(String key){
 92         return key == null? null: redisTemplate.opsForValue().get(key);
 93     }
 94 
 95     /**
 96      * 設定普通快取
 97      * @param key 鍵
 98      * @param value 值
 99      * @return
100      */
101     public boolean set(String key, Object value){
102         try{
103             redisTemplate.opsForValue().set(key,value);
104             return  true;
105         }catch (Exception e){
106             e.printStackTrace();
107             return false;
108         }
109     }
110 
111     /**
112      * 設定快取放入,並設定時間
113      * @param key 鍵
114      * @param value 值
115      * @param time 時間秒(time值小於0,怎設定無限期)
116      * @return
117      */
118     public  boolean set(String key,Object value, long time){
119         try{
120             if(time > 0){
121                 redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);
122             }else {
123                 redisTemplate.opsForValue().set(key,value);
124             }
125             return true;
126         }catch (Exception e){
127             e.printStackTrace();
128             return false;
129         }
130     }
131 
132     /**
133      * 遞增
134      * @param key 鍵
135      * @param delta 要增加的值
136      * @return
137      */
138     public long incr(String key,long delta){
139         if(delta < 0){
140             throw new RuntimeException("遞增因子,必須大於0");
141         }
142         return  redisTemplate.opsForValue().increment(key,delta);
143     }
144 
145     /**
146      * 遞減
147      * @param key 鍵
148      * @param delta 要減小的值
149      * @return
150      */
151     public long descr(String key ,long delta){
152         if(delta < 0){
153             throw new RuntimeException("遞減因子,必須大於0");
154         }
155         return  redisTemplate.opsForValue().increment(key,-delta);
156     }
157     //endregion
158     //region hash
159     /**
160      * 向一張hash表中放入資料,如果不存在將建立
161      * @param key 鍵
162      * @param item 項
163      * @param value 值
164      * @return
165      */
166     public  boolean hset(String key, String item, Object value){
167         try{
168             redisTemplate.opsForHash().put(key,item,value);
169         }catch (Exception e){
170             e.printStackTrace();
171             return false;
172         }
173         return true;
174     }
175 
176     /**
177      * 向一張表中放入資料,如果不存在,則建立
178      * @param key 鍵
179      * @param item 項
180      * @param value 值
181      * @param time 時間(秒),如果已存在的hash表有時間,這裡將會替換原有的時間
182      * @return
183      */
184     public boolean hset(String key, String item, Object value, long time){
185         try{
186             redisTemplate.opsForHash().put(key,item,value);
187             if(time > 0){
188                 redisTemplate.expire(key,time, TimeUnit.SECONDS);
189             }
190         }catch (Exception e){
191             e.printStackTrace();
192             return false;
193         }
194         return true;
195     }
196 
197     /**
198      * 刪除hash表中的值
199      * @param key 鍵
200      * @param items 項,可以多個,不能為空
201      */
202     public  void hdel(String key, Object ...items){
203         redisTemplate.opsForHash().delete(key, items);
204     }
205 
206     /**
207      * 獲取Hash值
208      * @param key 鍵,不能為空
209      * @param item 專案不能為空
210      * @return
211      */
212     public  Object hget(String key, String item){
213         return redisTemplate.opsForHash().get(key,item);
214     }
215 
216     /**
217      * 獲取HashKey的所有鍵值
218      * @param key 鍵
219      * @return
220      */
221     public  Map<Object,Object> hmget(String key){
222         return  redisTemplate.opsForHash().entries(key);
223     }
224     /**
225      * 設定HashKey的所有鍵值
226      * @param key 鍵
227      * @param map 對應多個鍵值
228      * @return
229      */
230     public  boolean hmset(String key, Map<String , Object> map){
231         try {
232             redisTemplate.opsForHash().putAll(key,map);
233         }catch (Exception e){
234             e.printStackTrace();
235             return false;
236         }
237         return  true;
238     }
239 
240     /**
241      * HashSet 並設定時間
242      * @param key 鍵
243      * @param map 對應多個鍵值
244      * @param time 時間(秒)
245      * @return
246      */
247     public  boolean hmset(String key, Map<String , Object> map,long time){
248         try {
249             redisTemplate.opsForHash().putAll(key,map);
250             if(time > 0){
251                 redisTemplate.expire(key,time,TimeUnit.SECONDS);
252             }
253         }catch (Exception e){
254             e.printStackTrace();
255             return false;
256         }
257         return  true;
258     }
259 
260     /**
261      * 判斷hash表中是否有該項值
262      * @param key 鍵,不能為空
263      * @param item 項,不能為空
264      * @return
265      */
266     public  boolean hHashKey(String  key,String item){
267         return  redisTemplate.opsForHash().hasKey(key,item);
268     }
269 
270     /**
271      * hash遞增,如果不存在就會建立一個,並把新增後的值返回
272      * @param key 鍵
273      * @param item 項
274      * @param by 要增大幾(大於0)
275      * @return
276      */
277     public double hinc(String key, String item, double by){
278         return  redisTemplate.opsForHash().increment(key,item,by);
279     }
280 
281     /**
282      * hash遞減
283      * @param key 鍵
284      * @param item 項
285      * @param by 要減小几(大於0)
286      * @return
287      */
288     public double hdescr(String key, String item, double by){
289         return  redisTemplate.opsForHash().increment(key,item,-by);
290     }
291     //endregion
292     //region set
293     /**
294      * 根據key,獲取set的所有值
295      * @param key 鍵
296      * @return
297      */
298     public  Set<Object> sGet(String key){
299         try {
300             return redisTemplate.opsForSet().members(key);
301         }catch (Exception e){
302             e.printStackTrace();
303             return  null;
304         }
305     }
306 
307     /**
308      * 根據value一個set查詢,是否存在
309      * @param key 鍵
310      * @param value 值
311      * @return
312      */
313     public boolean sHashKey(String key, Object value){
314         try {
315             return redisTemplate.opsForSet().isMember(key,value);
316         }catch (Exception e){
317             e.printStackTrace();
318             return false;
319         }
320     }
321 
322     /**
323      * 將資料放入set快取
324      * @param key 鍵
325      * @param values 值,可以時多個
326      * @return
327      */
328     public  long sSet(String key, Object... values){
329         try {
330             return  redisTemplate.opsForSet().add(key,values);
331         }catch (Exception e){
332             e.printStackTrace();
333             return  0;
334         }
335     }
336     /**
337      * 將資料放入set快取,並設定時間
338      * @param key 鍵
339      * @param time 時間(秒)
340      * @param values 值,可以時多個
341      * @return
342      */
343     public  long sSetAndTime(String key,long time, Object... values){
344         try {
345             long count =  redisTemplate.opsForSet().add(key,values);
346             if(time > 0){
347                 redisTemplate.expire(key,time,TimeUnit.SECONDS);
348             }
349             return  count;
350         }catch (Exception e){
351             e.printStackTrace();
352             return  0;
353         }
354     }
355 
356     /***
357      * 獲取Set快取長度
358      * @param key
359      * @return
360      */
361     public  long sGetSetSize(String key){
362         try {
363             return  redisTemplate.opsForSet().size(key);
364         }catch (Exception e){
365             e.printStackTrace();
366             return  0;
367         }
368     }
369 
370     /**
371      * 移除值為value的快取
372      * @param key
373      * @param values
374      * @return
375      */
376     public  long setRemove(String key, Object ... values){
377         try {
378             return  redisTemplate.opsForSet().remove(key,values);
379         }catch (Exception e){
380             e.printStackTrace();
381             return 0;
382         }
383     }
384     //endregion
385     //region list
386 
387     /**
388      * 獲取list 快取內容
389      * @param key 鍵
390      * @param start 開始位置
391      * @param end 結束位置 0 到-1代表所有值
392      * @return
393      */
394     public List<Object> lGet(String key, long start, long end){
395         try {
396             return redisTemplate.opsForList().range(key,start,end);
397         }catch (Exception e){
398             e.printStackTrace();
399             return null;
400         }
401     }
402 
403     /**
404      * 獲取list快取長度
405      * @param key 鍵
406      * @return
407      */
408     public  long lGetListSize(String key){
409         try{
410             return  redisTemplate.opsForList().size(key);
411         }catch (Exception e){
412             e.printStackTrace();
413             return  0;
414         }
415     }
416 
417     /**
418      * 透過索引獲取list的值
419      * @param key 鍵
420      * @param index 索引(> 0,索引),-1表尾,-2倒數第二個元素,以此類推
421      * @return
422      */
423     public  Object lGetIndex(String key,long index){
424         try{
425             return redisTemplate.opsForList().index(key,index);
426         }catch (Exception e){
427             e.printStackTrace();
428             return  null;
429         }
430     }
431 
432     /**
433      * 將list快取
434      * @param key 鍵
435      * @param value 值
436      * @return
437      */
438     public long lSet(String key, Object value){
439         try{
440            return redisTemplate.opsForList().rightPush(key,value);
441         }catch (Exception e){
442             e.printStackTrace();
443             return 0;
444         }
445     }
446 
447     /**
448      * 將list快取,並設定時間
449      * @param key 鍵
450      * @param value 值
451      * @param time 時間(秒)
452      * @return
453      */
454     public  long lSet(String key, Object value, long time){
455         try{
456             long result =  redisTemplate.opsForList().rightPush(key,value);
457             if(time > 0){
458                 redisTemplate.expire(key,time,TimeUnit.SECONDS);
459             }
460             return result;
461         }catch (Exception e){
462             e.printStackTrace();
463             return 0;
464         }
465     }
466 
467     /**
468      * 將list放入快取
469      * @param key 鍵
470      * @param value 值
471      * @return
472      */
473     public long  lSet(String key, List<Object> value){
474         try{
475             return redisTemplate.opsForList().rightPushAll(key,value);
476         }catch (Exception e){
477             e.printStackTrace();
478             return 0;
479         }
480     }
481 
482     /**
483      * 將list放入快取
484      * @param key 鍵
485      * @param value 值
486      * @param time 時間(秒)
487      * @return
488      */
489     public long  lSet(String key, List<Object> value,long time){
490         try{
491             long result =  redisTemplate.opsForList().rightPushAll(key,value);
492             if(time > 0){
493                 redisTemplate.expire(key,time,TimeUnit.SECONDS);
494             }
495             return result;
496         }catch (Exception e){
497             e.printStackTrace();
498             return 0;
499         }
500     }
501 
502     /**
503      * 根據索引修改list的某條資料
504      * @param key 鍵
505      * @param index 索引
506      * @param value 值
507      * @return
508      */
509     public boolean lUpdateIndex(String key,long index, Object value){
510         try{
511             redisTemplate.opsForList().set(key,index,value);
512             return  true;
513         }catch (Exception e){
514             e.printStackTrace();
515             return false;
516         }
517     }
518 
519     /**
520      * 移除N個值為value
521      * @param key 鍵
522      * @param count 移除多少個
523      * @param value 值
524      * @return
525      */
526     public long lRemove(String key, long count, String value){
527        try {
528            return  redisTemplate.opsForList().remove(key,count,value);
529        }catch (Exception e){
530            e.printStackTrace();
531            return  0;
532        }
533     }
534     // endregion
535 }

相關文章