# 六角鼠年鐵人賽 Week 22 - Spring Boot - Java & Redis 範例
==大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai==
## Albert Einstein
:::info
Life is like riding a bicycle. To keep your balance, you must keep moving.
:::
## 主題
這週來分享如何使用 Java 建立並操作 Redis 的範例,範例非常簡短,著重在設定連線參數與了解物件兩件事情上。
> 因為工作關係,連續兩週上 6 天班,真是累到身體無法負荷。
## 範例
> 1. 延續前幾週的範例方式,Kai 全部都實作在同一個專案中,有興趣的人可以私信我分享。
> 2. redisTestController2.java 只是嘗試性的 Class 因此不會在文中出現。

### build.gradle
> 在 Gradle 設定中增加關於 redis 的套件
```xml
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}
```
### application.properties
> 建立 application.properties 並加上 redis 連線與連線池設定
```text=
# REDIS (RedisProperties)
# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器地址(下面為 Docker Redis 預設的位置)
spring.redis.host= 192.168.99.100
# Redis伺服器連線埠
spring.redis.port=6379
# Redis伺服器連線密碼(預設為空)
spring.redis.password=
# 連線池最大連線數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連線池最大等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 連線池中的最大空閒連線
spring.redis.jedis.pool.max-idle=8
# 連線池中的最小空閒連線
spring.redis.jedis.pool.min-idle=0
# 連線超時時間(毫秒)(不要設置為0,不然會很常發生 Connect time out 狀況)
spring.redis.timeout=5000
```
### redisTestController.class
> 測試用的 API
```java=
package kai.com.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class redisTestController implements Serializable {
@Autowired
RedisTemplate redisTemplate;
public void setSerializer(){
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
}
@RequestMapping("/saveTest")
public resultBean command(){
setSerializer();
String testKey = "testObject";
String testValue = "Hello World!";
redisTemplate.opsForValue().setIfAbsent(testKey,testValue);
Map<String, String> testMap = new HashMap<String, String>();
testMap.putIfAbsent("testMap_child1","1000");
testMap.putIfAbsent("testMap_child2","2000");
redisTemplate.opsForHash().putAll("testMap", testMap);
return new resultBean("ok","saveTest()");
}
@RequestMapping("/saveManually/{keyName}/{keyValue}")
public resultBean command2(@PathVariable("keyName") String keyName, @PathVariable("keyValue") String keyValue){
setSerializer();
redisTemplate.opsForValue().setIfAbsent(keyName,keyValue);
return new resultBean("ok","saveManually()");
}
@RequestMapping("/getTest/{keyName}")
public resultBean getResult(@PathVariable("keyName") String keyName){
setSerializer();
return new resultBean("ok",redisTemplate.opsForValue().get(keyName).toString());
}
@RequestMapping("/getTestMap/{keyName}")
public List<resultBean> getResult2(@PathVariable("keyName") String keyName){
setSerializer();
List<resultBean> returnList = new ArrayList<resultBean>();
Map<String, String> map = redisTemplate.opsForHash().entries(keyName);
for(String key : map.keySet())
returnList.add(new resultBean(key, map.get(key)));
return returnList;
}
}
```
> 準備了幾個測試用的 API,有自動增加資料的;手動增加資料的;GET 的部分也有分成取得一般字串跟 MAP 型態的
### resultBean.java
> 回傳訊息用的 Bean
```java=
package kai.com.redis;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class resultBean {
public String status;
public String response;
}
```
### 打 API 1 進行建立測試資料

### 取出成果


> Map 部分在 API 4 經過特殊處理取得
### 打 API 2 進行手動建立資料

### 成果

## 物件與重要細節說明
### redisTemplate
是 Java 用來與 Redis 溝通的物件,扮演舉足輕重的角色,在設定的部分可以看到幾乎只需要把連線參數寫入 application.properties 即可。
也可以採用舊式的 jedisConnectionFactory 做設定,但使用上來說這樣的方式已經不建議採用了。

這是因為由 Spring-Data-Redis 套件的處理,底層已經是透過 Jedis 的方式做連結了,在 SpringBoot 的部分省下了這個功。讓我們只需要以短短兩行 code 便可以使用 redis 的各種功能。
```java=
@Autowired
RedisTemplate redisTemplate;
```
### Serializable
在資料送入 redis 的過程中必須確保資料已經經過序列化處理,因此會看到 controller.java 實作了 Serializable;且 redisTemplate 也經過了序列化處理。
```java=
public void setSerializer(){
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
}
```
**如果不處理會怎樣?**
你會看到儲存進入的 Key 與 Value 變成下列這樣
> 一般的 Key 未被序列化

> HKey field 未被序列化

## 結語
:::danger
這週主要就講一下如何透過 Java 去操作建立起來的 Redis-Server,許多地方其實是看各位觀眾去應用了,畢竟 Redis 是一個 NoSQL DB,基本的方法與知識帶入門就可以增廣很多視野。
另外 Kai 有在網路上找到一篇很好的 Cache 處理文章分享給各位,Kai 自己也有嘗試,這位大神寫得很棒! Kai 就不在多花時間寫相同的東西了。
[SpringBoot 使用redis並實現cache機制 by 陳柏熹 發表於昕力大學 技術資訊共享專業論壇 ](https://tpu.thinkpower.com.tw/tpu/articleDetails/1525)
後續還有很多題材可以寫,目前規劃了快10個大項目... (汗顏
如果每一個項目都要向 Redis 寫這麼細,那大概寫到明年還在寫吧XD
~~下一篇就會做一個 Redis 特色功能的介紹與總結,然後下下篇就會開啟新的篇章了!~~
下一篇會介紹 Redis PUB/SUB 的功能~
[六角鼠年鐵人賽 Week 23 - Spring Boot - Redis Pub/Sub 功能介紹](/npde88CfQvyLQg2FeaZiYA)
PS: 10個項目都跟 Spring Cloud 無關... 何年何月才能寫到 Spring Cloud 系列呢"
:::
首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA)
###### tags: `Redis`,`w3HexSchool`