昨天在開發業務時,打算加入緩存層來提升系統響應速度。查找了一些資料,發現 Spring 的緩存功能十分強大!只須要添加少許的代碼,就能夠輕鬆緩存方法所返回的對象。這篇文章經過描述一個實際使用例子,介紹 Spring Cache 的使用限制以及注意事項。java
打開 build.gradle 文件,添加 Spring Cache 依賴。redis
implementation 'org.springframework.boot:spring-boot-starter-cache' implementation 'org.springframework.boot:spring-boot-starter-data-redis'
@Data @AllArgsConstructor public class Post implements Serializable { private Long id; private String title; private String content; }
PS:這裏使用到了 Lombok 插件,若是不熟悉可先查詢相關資料進行了解。spring
public interface PostRepository { Post getById(Long id); }
@Component public class PostRepositoryImpl implements PostRepository { @Override public Post getById(Long id) { // 模擬查詢時間 simulateSlowService(); return new Post(100L, "title", "content"); } private void simulateSlowService() { try { Long time = 3000L; Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } } }
@RestController public class PostController { private final PostRepository postRepository; public PostController(PostRepository postRepository) { this.postRepository = postRepository; } @GetMapping("posts/{id}") public Post getPostById(@PathVariable("id") Long id) { return postRepository.getById(id); } }
針對一些不容易被修改的資源,若是每次都須要到持久化數據庫中進行查詢,無疑是十分浪費的,體驗也差,下面咱們使用 Spring Cache 來改進一波。數據庫
@EnableCaching @SpringBootApplication public class CacheApplication { public static void main(String[] args) { SpringApplication.run(CacheApplication.class, args); } }
添加 @EnableCaching 註解啓動 Spring Cache。數組
spring: cache: type: redis redis: host: 127.0.0.1 port: 6379
這裏用 Redis 做爲緩存引擎,若是小夥伴想用其餘引擎,可自行查閱文檔進行配置。緩存
@RestController public class PostController { private final PostRepository postRepository; public PostController(PostRepository postRepository) { this.postRepository = postRepository; } @Cacheable(cacheNames = "getPostById", key = "#id") @GetMapping("posts/{id}") public Post getPostById(@PathVariable("id") Long id) { return postRepository.getById(id); } }
使用 @Cacheable 註解 getPostById 方法,使用了 cacheNames 和 key 參數。這裏先不展開說,下面會集中梳理幾種註解以及它們的參數意義。app
Spring Cache 經常使用的 5 個註解,分別是:less
在啓動類添加 @EnableCaching 註解讓系統開啓緩存功能。ide
功能是開啓緩存,能夠標記在類上或者是方法上。在調用方法時,會先從緩存中獲取結果,若不存在再執行方法。主要參數包括 cacheNames、key、condition 和 unless 等。函數
針對方法配置,與 @Cacheable 不一樣的地方在於它每次都會觸發真實方法的調用。簡單來講就是更新緩存數據。主要參數和 @Cacheable 一致。
針對方法配置,用來從緩存中移除相應數據。除了與 @Cacheable 相同的參數之外,還有 allEntries 和 beforeInvocation。
該註解是一個類級註解,可讓類下面的方法共享 cacheNames、keyGenerator、cacheManager 和 cacheResolver 參數。
這裏是爲了讓咱們的緩存註解支持自定義 TTL 失效時間,相似下面這種效果。
// 3600 秒後緩存集合自動過時 @Cacheable(cacheNames = "getPostById#3600", key = "#id")
爲了實現這種效果,咱們建立一個 CustomRedisCacheManager 自定義類,以下所示。
public class CustomRedisCacheManager extends RedisCacheManager { public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) { super(cacheWriter, defaultCacheConfiguration); } @Override protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { String[] array = StringUtils.delimitedListToStringArray(name, "#"); name = array[0]; if (array.length > 1) { long ttl = Long.parseLong(array[1]); cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl)); } return super.createRedisCache(name, cacheConfig); } }
使用自定義 CustomRedisCacheManager 配置 CacheConfig。
public class CacheConfig extends CachingConfigurerSupport { @Value("${spring.redis.host}") private String redisHost; @Value("${spring.redis.port}") private Integer redisPort; @Value("${spring.redis.database}") private Integer redisDatabase; @Override @Bean public CacheManager cacheManager() { RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofDays(1)) .computePrefixWith(cacheName -> "caching:" + cacheName); return new CustomRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()), defaultCacheConfig); } @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(); configuration.setHostName(redisHost); configuration.setPort(redisPort); configuration.setDatabase(redisDatabase); return new LettuceConnectionFactory(configuration); } }
本文主要介紹了 Spring Cache 的基本使用方式和經常使用註解。後續文章準備深刻了解其底層原理。
歡迎你們關注個人公衆號「是然的筆記本」。
再會!