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 }