# 六角鼠年鐵人賽 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 因此不會在文中出現。 ![](https://i.imgur.com/xCKq3qZ.png) ### 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 進行建立測試資料 ![](https://i.imgur.com/PDFsOfz.png) ### 取出成果 ![](https://i.imgur.com/iyH9auq.png) ![](https://i.imgur.com/Mmligqh.png) > Map 部分在 API 4 經過特殊處理取得 ### 打 API 2 進行手動建立資料 ![](https://i.imgur.com/UyFf36w.png) ### 成果 ![](https://i.imgur.com/TWb6OKl.png) ## 物件與重要細節說明 ### redisTemplate 是 Java 用來與 Redis 溝通的物件,扮演舉足輕重的角色,在設定的部分可以看到幾乎只需要把連線參數寫入 application.properties 即可。 也可以採用舊式的 jedisConnectionFactory 做設定,但使用上來說這樣的方式已經不建議採用了。 ![](https://i.imgur.com/pzH7pfH.png) 這是因為由 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 未被序列化 ![](https://i.imgur.com/nQ57rDB.png) > HKey field 未被序列化 ![](https://i.imgur.com/9CN4RJ7.png) ## 結語 :::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`