日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

spring boot 缓存_SpringBoot 应用 Redis 声明式缓存

發布時間:2025/3/21 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot 缓存_SpringBoot 应用 Redis 声明式缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是聲明式緩存 ?

Spring 框架提供一種抽象的緩存機制,且 Spring 只提供接口,不提供緩存的具體實現。所以在程序中使用時,需要有具體緩存的實現。目前支持的常見的緩存比如 JDK ConcurrentMap-based Cache、Ehcache、Redis、Caffeine Cache、Guava Cache 等。

所謂聲明式緩存,即使用 Spring 框架提供的注解來使用緩存功能。這就需要知道一些常用的注解:

  • @EnableCaching

Spring 默認沒有開啟緩存注解支持,可以在配置類上使用該注解進行開啟。

  • @Cacheable

程序在執行方法時首先會去緩存中檢查 key 對應的 value 是否存在。如果存在,則方法體不再執行,直接取緩存中的 value 返回;否則執行方法體,并將方法的返回值進行緩存。@Cacheable 注解的使用傾向于減少方法的執行。

  • @CachePut

方法執行完畢之后,將返回值 update 或者 insert 到緩存中。

  • @CacheEvict

方法執行完畢之后,將緩存刪除。

更多關于 Spring 框架緩存注解的說明可以參考官方文檔:Spring Boot Caching

測試環境說明

  • SpringBoot版本:2.0.2.RELEASE
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.2.RELEASE</version><relativePath/> </parent>
  • Redis 版本:3.2.9,pom 依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
  • MySQL 版本:8.0.12,pom 依賴:
<!-- Java Persistence API, ORM 規范 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 數據庫連接 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- MySQL 驅動, 注意, 這個需要與 MySQL 版本對應 --> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.12</version><scope>runtime</scope> </dependency>
  • mock 數據 sql:
-- 測試數據庫 CREATE DATABASE IF NOT EXISTS test;-- 城市信息表 CREATE TABLE IF NOT EXISTS `test`.`city_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增 id',`city` varchar(128) NOT NULL DEFAULT '' COMMENT '城市名稱',`longitude` bigint(20) NOT NULL DEFAULT '0' COMMENT '經度(100倍存儲)',`latitude` bigint(20) NOT NULL DEFAULT '0' COMMENT '緯度(100倍存儲)',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='城市信息表';-- fake 測試數據 INSERT INTO `city_info` (`id`, `city`, `longitude`, `latitude`) VALUES(1, '合肥', 11717, 3152),(2, '安慶', 11702, 3031),(3, '宿州', 11658, 3338);

測試代碼

代碼中已經給出了詳細的注釋說明,且使用方法也比較簡單,不做過多解釋。

Redis 配置

/*** <h1>Redis 配置</h1>* 繼承 CachingConfigurerSupport 重寫 CacheManager 和 KeyGenerator* Created by Qinyi.*/ @EnableCaching // 啟用緩存功能, 默認不啟用 @Configuration public class RedisConfig extends CachingConfigurerSupport {private final RedisConnectionFactory redisConnectionFactory;@Autowiredpublic RedisConfig(RedisConnectionFactory redisConnectionFactory) {this.redisConnectionFactory = redisConnectionFactory;}/*** <h2>配置 CacheManager: 序列化方式、過期時間</h2>* */@Overridepublic CacheManager cacheManager() {// 初始化一個 RedisCacheWriter// RedisCacheWriter 提供了對 Redis 的 set、setnx、get 等命令的訪問權限// 可以由多個緩存實現共享,并負責寫/讀來自 Redis 的二進制數據RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);// 設置 CacheManager 的值序列化方式RedisSerializer<Object> jsonSerializer = new JdkSerializationRedisSerializer();RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);// 提供 Redis 的配置RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);// 設置默認超過期時間是 30 秒defaultCacheConfig.entryTtl(Duration.ofSeconds(30));// 初始化 RedisCacheManager 返回return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);}/*** <h2>定義 key 生成器: 類名、方法名、參數列表</h2>* 自定義 KeyGenerator 的核心思想是保證 key 不會沖突* 默認的是 SimpleKeyGenerator, 它使用方法參數組合生成的一個 key, 這里存在一個問題:* 如果2個方法, 參數是一樣的. 但執行邏輯不同, 那么將會導致執行第二個方法時命中第一個方法的緩存. 所以, 通常需要自定義.* */@Overridepublic KeyGenerator keyGenerator() {return (clazz, method, args) -> {StringBuilder sb = new StringBuilder();sb.append(clazz.getClass().getName()).append("#");sb.append(method.getName()).append("(");for (Object obj : args) {sb.append(obj.toString()).append(",");}sb.deleteCharAt(sb.length() - 1);sb.append(")");return sb.toString();};} }

城市信息實體

/*** <h1>城市信息實體</h1>* Created by Qinyi.*/ @Data @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "city_info") public class CityInfo implements Serializable {/** 自增主鍵 */@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Long id;/** 城市名稱 */@Basic@Column(name = "city", nullable = false)private String city;/** 經度 */@Basic@Column(name = "longitude", nullable = false)private Long longitude;/** 緯度 */@Basic@Column(name = "latitude", nullable = false)private Long latitude; }

城市信息服務接口定義

/*** <h1>城市信息服務接口定義</h1>* Created by Qinyi.*/ public interface ICityInfoService {/*** <h2>根據 id 獲取城市信息</h2>* @param id 記錄 id* @return {@link CityInfo}* */CityInfo getCityInfoById(Long id);/*** <h2>更新城市信息</h2>* @param newObj 新的城市信息* @return {@link CityInfo}* */CityInfo updateCityInfo(CityInfo newObj);/*** <h2>根據 id 刪除城市信息</h2>* @param id 記錄 id* */void deleteCityInfoById(Long id); }

城市信息服務接口定義

/*** <h1>城市信息服務接口定義</h1>* Created by Qinyi.*/ @Slf4j @Service public class CityInfoServiceImpl implements ICityInfoService {/** CityInfo Dao */private final CityInfoRepository repository;@Autowiredpublic CityInfoServiceImpl(CityInfoRepository repository) {this.repository = repository;}/*** <h2>根據 id 獲取城市信息</h2>* 如果不指定 key, 則會使用 KeyGenerator 來生成 key* 1. 如果指定了 key = "#id", redis 中的 key 是 city_info::1* 2. 如果使用自定義的 KeyGenerator(不指定 key), redis 中的 key 是:* city_info::com.imooc.ad.service.impl.CityInfoServiceImpl#getCityInfoById(1)* */@Override@SuppressWarnings("all")@Cacheable(cacheNames = "city_info", key = "#id") // @Cacheable(cacheNames = "city_info")public CityInfo getCityInfoById(Long id) {log.info("get CityInfo by id: {}", id.toString());return repository.findById(id).get();}@Override@CachePut(cacheNames="city_info", key="#newObj.id")public CityInfo updateCityInfo(CityInfo newObj) {log.info("update CityInfo: {}", JSON.toJSONString(newObj));return repository.save(newObj);}@Override@CacheEvict(cacheNames = "city_info", key = "#id")public void deleteCityInfoById(Long id) {log.info("delete CityInfo by id: {}", id.toString());repository.deleteById(id);} }

Spring 聲明式緩存測試用例

/*** <h1>Spring 聲明式緩存測試用例</h1>* Created by Qinyi.*/ @RunWith(SpringRunner.class) @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class CacheAnnotationTest {@Autowiredprivate ICityInfoService cityInfoService;/*** <h2>測試多次獲取, 可以直接從緩存(Redis)中獲取數據, 而不用查詢數據庫</h2>* */@Testpublic void testGetCityInfoById() {System.out.println(JSON.toJSONString(cityInfoService.getCityInfoById(1L)));}/*** <h2>測試更新緩存</h2>* */@Testpublic void testUpdateCityInfo() {System.out.println(JSON.toJSONString(cityInfoService.updateCityInfo(new CityInfo(1L, "合肥", 11717L, 3153L))));}/*** <h2>測試刪除緩存</h2>* */@Testpublic void testDeleteCityInfoById() {cityInfoService.deleteCityInfoById(1L);} }

執行測試用例之后,可以在 Redis 中看到自動生成的緩存 KV:

127.0.0.1:6379> keys * 1) "city_info::1" 2) "city_info::com.imooc.ad.service.impl.CityInfoServiceImpl#getCityInfoById(1)" 127.0.0.1:6379> type city_info::1 string 127.0.0.1:6379> get city_info::1 "xacxedx00x05srx00x1ccom.imooc.ad.entity.CityInfoxe2/O>xd3xe6xeexc8x02x00x04Lx00x04citytx00x12Ljava/lang/String;Lx00x02idtx00x10Ljava/lang/Long;Lx00blatitudeqx00~x00x02Lx00tlongitudeqx00~x00x02xptx00x06xe5x90x88xe8x82xa5srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00x00x00x00x00x01sqx00~x00x05x00x00x00x00x00x00x0cPsqx00~x00x05x00x00x00x00x00x00-xc5" 12

注:
作者:張勤一
出處:http://www.imooc.com/article/283946

總結

以上是生活随笔為你收集整理的spring boot 缓存_SpringBoot 应用 Redis 声明式缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。