您好,登錄后才能下訂單哦!
這篇文章主要講解了“SpringBoot用Redis實(shí)現(xiàn)數(shù)據(jù)緩存”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“SpringBoot用Redis實(shí)現(xiàn)數(shù)據(jù)緩存”吧!
我們?nèi)粘I钪校?jīng)常會(huì)接觸聽到緩存這個(gè)詞,例如,瀏覽器清空緩存,處理器緩存大小,磁盤緩存等等。經(jīng)過分類,可以將緩存分為:
硬件緩存: 一般指的是機(jī)器上的 CPU、硬盤等等組件的緩存區(qū)間,一般是利用的內(nèi)存作為一塊中轉(zhuǎn)區(qū)域,都通過內(nèi)存交互信息,減少系統(tǒng)負(fù)載,提供傳輸效率。
客戶端緩存: 一般指的是某些應(yīng)用,例如瀏覽器、手機(jī)App、視頻緩沖等等,都是在加載一次數(shù)據(jù)后將數(shù)據(jù)臨時(shí)存儲(chǔ)到本地,當(dāng)再次訪問時(shí)候先檢查本地緩存中是否存在,存在就不必去遠(yuǎn)程重新拉取,而是直接讀取緩存數(shù)據(jù),這樣來減少遠(yuǎn)端服務(wù)器壓力和加快載入速度。
服務(wù)端緩存: 一般指遠(yuǎn)端服務(wù)器上,考慮到客戶端請(qǐng)求量多,某些數(shù)據(jù)請(qǐng)求量大,這些熱點(diǎn)數(shù)據(jù)經(jīng)常要到數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),給數(shù)據(jù)庫(kù)造成壓力,還有就是 IO、網(wǎng)絡(luò)等原因有一定延遲,響應(yīng)客戶端較慢。所以,在一些不考慮實(shí)時(shí)性的數(shù)據(jù)中,經(jīng)常將這些數(shù)據(jù)存在內(nèi)存中(內(nèi)存速度非??欤?,當(dāng)請(qǐng)求時(shí)候,能夠直接讀取內(nèi)存中的數(shù)據(jù)及時(shí)響應(yīng),借鑒Redis實(shí)戰(zhàn)學(xué)習(xí)筆記。
用緩存,主要有解決 高性能 與 高并發(fā) 與 減少數(shù)據(jù)庫(kù)壓力。緩存本質(zhì)就是將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,當(dāng)數(shù)據(jù)沒有發(fā)生本質(zhì)變化的時(shí)候,我們應(yīng)盡量避免直接連接數(shù)據(jù)庫(kù)進(jìn)行查詢,因?yàn)椴l(fā)高時(shí)很可能會(huì)將數(shù)據(jù)庫(kù)壓塌,而是應(yīng)去緩存中讀取數(shù)據(jù),只有緩存中未查找到時(shí)再去數(shù)據(jù)庫(kù)中查詢,這樣就大大降低了數(shù)據(jù)庫(kù)的讀寫次數(shù),增加系統(tǒng)的性能和能提供的并發(fā)量。
優(yōu)點(diǎn):
加快了響應(yīng)速度
減少了對(duì)數(shù)據(jù)庫(kù)的讀操作,數(shù)據(jù)庫(kù)的壓力降低。
缺點(diǎn):
內(nèi)存容量相對(duì)硬盤小。
緩存中的數(shù)據(jù)可能與數(shù)據(jù)庫(kù)中數(shù)據(jù)不一致。
因?yàn)閮?nèi)存斷電就清空數(shù)據(jù),存放到內(nèi)存中的數(shù)據(jù)可能丟失。
Redis 是一個(gè)高性能的 Key-Value 數(shù)據(jù)庫(kù),它是完全開源免費(fèi)的,而且 Redis 是一個(gè) NoSQL 類型數(shù)據(jù)庫(kù),是為了解決 高并發(fā)、高擴(kuò)展,大數(shù)據(jù)存儲(chǔ) 等一系列的問題而產(chǎn)生的數(shù)據(jù)庫(kù)解決方案,是一個(gè)非關(guān)系型的數(shù)據(jù)庫(kù)。但是,它也是不能替代關(guān)系型數(shù)據(jù)庫(kù),只能作為特定環(huán)境下的擴(kuò)充。
支持高可用: Redis 支持 master\slave 主\從機(jī)制、sentinal 哨兵模式、cluster 集群模式,這樣大大保證了 Redis 運(yùn)行的穩(wěn)定和高可用行。
支持多種數(shù)據(jù)結(jié)構(gòu): Redis 不僅僅支持簡(jiǎn)單的 Key/Value 類型的數(shù)據(jù),同時(shí)還提供 list、set、zset、hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
支持?jǐn)?shù)據(jù)持久化: 可以將內(nèi)存中的數(shù)據(jù)持久化在磁盤中,當(dāng)宕機(jī)或者故障重啟時(shí),可以再次加載進(jìn)如 Redis,從而不會(huì)或減少數(shù)據(jù)的丟失。
有很多工具與插件對(duì)其支持: Redis 已經(jīng)在業(yè)界廣泛使用,已經(jīng)是成為緩存的首選目標(biāo),所以很多語言和工具對(duì)其支持,我們只需要簡(jiǎn)單的操作就可以輕松使用。
Redis 支持的數(shù)據(jù)結(jié)構(gòu)類型包括:
字符串(string)
哈希表(hash)
列表(list)
集合(set)
有序集合(zset)
為了保證讀取的效率,Redis 把數(shù)據(jù)對(duì)象都存儲(chǔ)在內(nèi)存當(dāng)中,它可以支持周期性的把更新的數(shù)據(jù)寫入磁盤文件中。而且它還提供了交集和并集,以及一些不同方式排序的操作。
緩存穿透: 指查詢一個(gè)一定不存在的數(shù)據(jù),由于緩存是不命中時(shí)需要從數(shù)據(jù)庫(kù)查詢,查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到數(shù)據(jù)庫(kù)去查詢,造成緩存穿透。
緩存穿透幾種解決辦法:
緩存空值,在從 DB 查詢對(duì)象為空時(shí),也要將空值存入緩存,具體的值需要使用特殊的標(biāo)識(shí), 能和真正緩存的數(shù)據(jù)區(qū)分開,另外將其過期時(shí)間設(shè)為較短時(shí)間。
使用布隆過濾器,布隆過濾器能判斷一個(gè) key 一定不存在(不保證一定存在,因?yàn)椴悸∵^濾器結(jié)構(gòu)原因,不能刪除,但是舊值可能被新值替換,而將舊值刪除后它可能依舊判斷其可能存在),在緩存的基礎(chǔ)上,構(gòu)建布隆過濾器數(shù)據(jù)結(jié)構(gòu),在布隆過濾器中存儲(chǔ)對(duì)應(yīng)的 key,如果存在,則說明 key 對(duì)應(yīng)的值為空。
緩存擊穿: 某個(gè) key 非常熱點(diǎn),訪問非常頻繁,處于集中式高并發(fā)訪問的情況,當(dāng)這個(gè) key 在失效的瞬間,大量的請(qǐng)求就擊穿了緩存,直接請(qǐng)求數(shù)據(jù)庫(kù),就像是在一道屏障上鑿開了一個(gè)洞。
緩存擊穿幾種解決辦法:
設(shè)置二級(jí)緩存,或者設(shè)置熱點(diǎn)緩存永不過期,需要根據(jù)實(shí)際情況進(jìn)行配置。
使用互斥鎖,在執(zhí)行過程中,如果緩存過期,那么先獲取分布式鎖,在執(zhí)行從數(shù)據(jù)庫(kù)中加載數(shù)據(jù),如果找到數(shù)據(jù)就存入緩存,沒有就繼續(xù)該有的動(dòng)作,在這個(gè)過程中能保證只有一個(gè)線程操作數(shù)據(jù)庫(kù),避免了對(duì)數(shù)據(jù)庫(kù)的大量請(qǐng)求。
緩存雪崩: 當(dāng)緩存服務(wù)器重啟、或者大量緩存集中在某一個(gè)時(shí)間段失效,這樣在失效的時(shí)候,也會(huì)給后端系統(tǒng)(比如DB)帶來很大壓力,造成數(shù)據(jù)庫(kù)后端故障,從而引起應(yīng)用服務(wù)器雪崩。
緩存雪崩幾種解決辦法:
緩存組件設(shè)計(jì)高可用,緩存高可用是指,存儲(chǔ)緩存的組件的高可用,能夠防止單點(diǎn)故障、機(jī)器故障、機(jī)房宕機(jī)等一系列問題。例如 Redis sentinel 和 Redis Cluster,都實(shí)現(xiàn)了高可用。
請(qǐng)求限流與服務(wù)熔斷降級(jí)機(jī)制,限制服務(wù)請(qǐng)求次數(shù),當(dāng)服務(wù)不可用時(shí)快速熔斷降級(jí)。
設(shè)置緩存過期時(shí)間一定的隨機(jī)分布,避免集中在同一時(shí)間緩存失效。
定時(shí)更新緩存策略,對(duì)于實(shí)時(shí)性要求不高的數(shù)據(jù),定時(shí)進(jìn)行更新。
使用緩存很大可能導(dǎo)致數(shù)據(jù)不一致問題,如下:
更熟數(shù)據(jù)庫(kù)成功 -> 更新緩存失敗 -> 數(shù)據(jù)不一致
更新緩存成功 -> 更新數(shù)據(jù)庫(kù)失敗 -> 數(shù)據(jù)不一致
更新數(shù)據(jù)庫(kù)成功 -> 淘汰緩存失敗 -> 數(shù)據(jù)不一致
淘汰緩存成功 -> 更新數(shù)據(jù)庫(kù)失敗 -> 查詢緩存mis
所以使用緩存時(shí)候,應(yīng)該結(jié)合實(shí)際情況,考慮緩存的數(shù)據(jù)是否有一致性需求。
spring-boot-starter-data-redis:
commons-pool2:
application 文件中添加連接 Redis 的配置參數(shù)
@Configuration public class RedisConfig { /** * 配置緩存管理器 * @param factory Redis 線程安全連接工廠 * @return 緩存管理器 */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { // 生成兩套默認(rèn)配置,通過 Config 對(duì)象即可對(duì)緩存進(jìn)行自定義配置 RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig() // 設(shè)置過期時(shí)間 10 分鐘 .entryTtl(Duration.ofMinutes(10)) // 設(shè)置緩存前綴 .prefixKeysWith("cache:user:") // 禁止緩存 null 值 .disableCachingNullValues() // 設(shè)置 key 序列化 .serializeKeysWith(keyPair()) // 設(shè)置 value 序列化 .serializeValuesWith(valuePair()); // 返回 Redis 緩存管理器 return RedisCacheManager.builder(factory) .withCacheConfiguration("user", cacheConfig).build(); } /** * 配置鍵序列化 * @return StringRedisSerializer */ private RedisSerializationContext.SerializationPair<String> keyPair() { return RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()); } /** * 配置值序列化,使用 GenericJackson2JsonRedisSerializer 替換默認(rèn)序列化 * @return GenericJackson2JsonRedisSerializer */ private RedisSerializationContext.SerializationPair<Object> valuePair() { return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()); } }
@Service @CacheConfig(cacheNames = "user") public class UserServiceImpl implements UserService { /** * 新增用戶 */ public User addUser(User user) { ...... } /** * 查詢用戶 */ @Cacheable(key = "#username") public User getUserByUsername(String username) { ...... } /** * 更新用戶 */ @CachePut(key = "#user.username") public User updateUser(User user) { ...... } /** * 刪除用戶 */ @CacheEvict(key = "#username") public void deleteByUsername(String username) { ...... } }
@CacheConfig: 一般配置在類上,指定緩存名稱,這個(gè)名稱是和上面“置緩存管理器”中緩存名稱的一致。
@Cacheable: 作用于方法上,用于對(duì)于方法返回結(jié)果進(jìn)行緩存,如果已經(jīng)存在該緩存,則直接從緩存中獲取,緩存的key可以從入?yún)⒅兄付?,緩存?value 為方法返回值。
@CachePut: 作用于方法上,無論是否存在該緩存,每次都會(huì)重新添加緩存,緩存的key可以從入?yún)⒅兄付ǎ彺娴膙alue為方法返回值,常用作于更新。
@CacheEvict: 作用于方法上,用于清除緩存
@Caching: 作用于方法上,用于一次性設(shè)置多個(gè)緩存。
上面注解中的常用配置參數(shù):
value: 緩存管理器中配置的緩存的名稱,這里可以理解為一個(gè)組的概念,緩存管理器中可以有多套緩存配置,每套都有一個(gè)名稱,類似于組名,這個(gè)可以配置這個(gè)值,選擇使用哪個(gè)緩存的名稱,配置后就會(huì)應(yīng)用那個(gè)緩存名稱對(duì)應(yīng)的配置。
key: 緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。
condition: 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進(jìn)行緩存。
unless: 不緩存的條件,和 condition 一樣,也是 SpEL 編寫,返回 true 或者 false,為 true 時(shí)則不進(jìn)行緩存。
@EnableCaching: 作用于類上,用于開啟注解功能。
使用 Spring Cache 雖然方便,但是也有很多局限性,因?yàn)樗嗍歉鶕?jù)請(qǐng)求參數(shù)命名 key,根據(jù)返回指設(shè)置 value,這樣很多情況下,我們想方法內(nèi)部進(jìn)行命名和操作有一定的限制。如果我們需要靈活設(shè)置緩存,可以不用 SpringCache 提供的注解,直接在代碼中使用 Spring-data-redis 包提供的方法,手動(dòng)操作 key 與 value。
opsForValue().set(String key, String value);
opsForValue().get(String key);
還有經(jīng)常要批量設(shè)置、讀取緩存,可以使用:
opsForValue().multiSet(Map map);
opsForValue().multiGet(List list);
下面是一個(gè)簡(jiǎn)單的 SpringBoot 項(xiàng)目,用于對(duì)用戶的增刪改查,這里使用 SpringCache 來模擬對(duì)數(shù)據(jù)進(jìn)行緩存,示例如下:
Maven 中引入 SpringBoot 和 Redis 依賴,因?yàn)槭褂昧?/p>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> </parent> <groupId>mydlq.club</groupId> <artifactId>springboot-redis-example</artifactId> <version>0.0.1</version> <name>springboot-redis-example</name> <description>Demo project for Spring Boot Redis</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
緩存配置類,里面配置緩存管理器,配置緩存的全局過期時(shí)間、序列化等參數(shù)。
import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.*; import java.time.Duration; /** * Redis 配置類 */ @Configuration public class RedisConfig { /** * 配置緩存管理器 * @param factory Redis 線程安全連接工廠 * @return 緩存管理器 */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { // 生成兩套默認(rèn)配置,通過 Config 對(duì)象即可對(duì)緩存進(jìn)行自定義配置 RedisCacheConfiguration cacheConfig1 = RedisCacheConfiguration.defaultCacheConfig() // 設(shè)置過期時(shí)間 10 分鐘 .entryTtl(Duration.ofMinutes(10)) // 設(shè)置緩存前綴 .prefixKeysWith("cache:user:") // 禁止緩存 null 值 .disableCachingNullValues() // 設(shè)置 key 序列化 .serializeKeysWith(keyPair()) // 設(shè)置 value 序列化 .serializeValuesWith(valuePair()); RedisCacheConfiguration cacheConfig2 = RedisCacheConfiguration.defaultCacheConfig() // 設(shè)置過期時(shí)間 30 秒 .entryTtl(Duration.ofSeconds(30)) .prefixKeysWith("cache:user_info:") .disableCachingNullValues() .serializeKeysWith(keyPair()) .serializeValuesWith(valuePair()); // 返回 Redis 緩存管理器 return RedisCacheManager.builder(factory) .withCacheConfiguration("user", cacheConfig1) .withCacheConfiguration("userInfo", cacheConfig2) .build(); } /** * 配置鍵序列化 * @return StringRedisSerializer */ private RedisSerializationContext.SerializationPair<String> keyPair() { return RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()); } /** * 配置值序列化,使用 GenericJackson2JsonRedisSerializer 替換默認(rèn)序列化 * @return GenericJackson2JsonRedisSerializer */ private RedisSerializationContext.SerializationPair<Object> valuePair() { return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()); } }
用戶實(shí)體類
User
用戶信息實(shí)體類
UserInfo
UserService
import mydlq.club.example.entity.User; /** * 用戶業(yè)務(wù)接口 */ public interface UserService { /** * 增加賬戶 * * @param user 賬戶 */ void addUser(User user); /** * 獲取賬戶 * * @param username 用戶名 * @return 用戶信息 */ User getUserByUsername(String username); /** * 修改賬戶 * * @param user 用戶信息 * @return 用戶信息 */ User updateUser(User user); /** * 刪除賬戶 * @param username 用戶名 */ void deleteByUsername(String username); }
UserInfoService
import mydlq.club.example.entity.UserInfo; /** * 用戶信息業(yè)務(wù)接口 */ public interface UserInfoService { /** * 增加用戶信息 * * @param userInfo 用戶信息 */ void addUserInfo(UserInfo userInfo); /** * 獲取用戶信息 * * @param name 姓名 * @return 用戶信息 */ UserInfo getByName(String name); /** * 修改用戶信息 * * @param userInfo 用戶信息 * @return 用戶信息 */ UserInfo updateUserInfo(UserInfo userInfo); /** * 刪除用戶信息 * @param name 姓名 */ void deleteByName(String name); }
實(shí)現(xiàn) UserService 與 UserInfoService 接口中的方法,里面使用 @Cacheable、@CachePut、@CacheEvict 三個(gè)注解完成對(duì)用戶與用戶信息數(shù)據(jù)的緩存。
UserServiceImpl(用戶業(yè)務(wù)實(shí)現(xiàn)類)
注意,為了演示方便,沒有連接數(shù)據(jù)庫(kù),臨時(shí)創(chuàng)建了個(gè)成員變量 userMap 來模擬數(shù)據(jù)庫(kù)存儲(chǔ)。
import mydlq.club.example.entity.User; import mydlq.club.example.service.UserService; import org.springframework.beans.BeanUtils; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.HashMap; @Service @CacheConfig(cacheNames = "user") public class UserServiceImpl implements UserService { private HashMap<String, User> userMap = new HashMap<>(); @Override public void addUser(User user) { userMap.put(user.getUsername(), user); } @Override @Cacheable(key = "#username",unless = "#result==null ") public User getUserByUsername(String username) { if (!userMap.containsKey(username)) { return null; } return userMap.get(username); } @Override @CachePut(key = "#user.username") public User updateUser(User user) { if (!userMap.containsKey(user.getUsername())){ throw new RuntimeException("不存在該用戶"); } // 獲取存儲(chǔ)的對(duì)象 User newUser = userMap.get(user.getUsername()); // 復(fù)制要更新的數(shù)據(jù)到新對(duì)象,因?yàn)椴荒芨挠脩裘畔?,所以忽? BeanUtils.copyProperties(user, newUser, "username"); // 將新的對(duì)象存儲(chǔ),更新舊對(duì)象信息 userMap.put(newUser.getUsername(), newUser); // 返回新對(duì)象信息 return newUser; } @Override @CacheEvict(key = "#username") public void deleteByUsername(String username) { userMap.remove(username); } }
UserInfoServiceImpl(用戶信息業(yè)務(wù)實(shí)現(xiàn))
注意,為了演示方便,沒有連接數(shù)據(jù)庫(kù),臨時(shí)創(chuàng)建了個(gè)成員變量 userInfoMap 來模擬數(shù)據(jù)庫(kù)存儲(chǔ)。
import mydlq.club.example.entity.UserInfo; import mydlq.club.example.service.UserInfoService; import org.springframework.beans.BeanUtils; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.HashMap; @Service @CacheConfig(cacheNames = "userInfo") public class UserInfoServiceImpl implements UserInfoService { private HashMap<String, UserInfo> userInfoMap = new HashMap<>(); @Override public void addUserInfo(UserInfo userInfo) { userInfoMap.put(userInfo.getName(), userInfo); } @Override @Cacheable(key = "#name", unless = "#result==null") public UserInfo getByName(String name) { if (!userInfoMap.containsKey(name)) { return null; } return userInfoMap.get(name); } @Override @CachePut(key = "#userInfo.name") public UserInfo updateUserInfo(UserInfo userInfo) { if (!userInfoMap.containsKey(userInfo.getName())) { throw new RuntimeException("該用戶信息沒有找到"); } // 獲取存儲(chǔ)的對(duì)象 UserInfo newUserInfo = userInfoMap.get(userInfo.getName()); // 復(fù)制要更新的數(shù)據(jù)到新對(duì)象,因?yàn)椴荒芨挠脩裘畔ⅲ院雎? BeanUtils.copyProperties(userInfo, newUserInfo, "name"); // 將新的對(duì)象存儲(chǔ),更新舊對(duì)象信息 userInfoMap.put(newUserInfo.getName(), newUserInfo); // 返回新對(duì)象信息 return newUserInfo; } @Override @CacheEvict(key = "#name") public void deleteByName(String name) { userInfoMap.remove(name); } }
UserController
import mydlq.club.example.entity.User; import mydlq.club.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * 用戶 Controller */ @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/{username}") public User getUser(@PathVariable String username) { return userService.getUserByUsername(username); } @PostMapping("/user") public String createUser(@RequestBody User user) { userService.addUser(user); return "SUCCESS"; } @PutMapping("/user") public User updateUser(@RequestBody User user) { return userService.updateUser(user); } @DeleteMapping("/user/{username}") public String deleteUser(@PathVariable String username) { userService.deleteByUsername(username); return "SUCCESS"; } }
UserInfoController
import mydlq.club.example.entity.UserInfo; import mydlq.club.example.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * 用戶信息 Controller */ @RestController public class UserInfoController { @Autowired private UserInfoService userInfoService; @GetMapping("/userInfo/{name}") public UserInfo getUserInfo(@PathVariable String name) { return userInfoService.getByName(name); } @PostMapping("/userInfo") public String createUserInfo(@RequestBody UserInfo userInfo) { userInfoService.addUserInfo(userInfo); return "SUCCESS"; } @PutMapping("/userInfo") public UserInfo updateUserInfo(@RequestBody UserInfo userInfo) { return userInfoService.updateUserInfo(userInfo); } @DeleteMapping("/userInfo/{name}") public String deleteUserInfo(@PathVariable String name) { userInfoService.deleteByName(name); return "SUCCESS"; } }
啟動(dòng)類中添加 @EnableCaching 注解開啟緩存。
感謝各位的閱讀,以上就是“SpringBoot用Redis實(shí)現(xiàn)數(shù)據(jù)緩存”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)SpringBoot用Redis實(shí)現(xiàn)數(shù)據(jù)緩存這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。