springboot整合spring @Cache和Redis
轉載自? springboot整合spring @Cache和Redis
spring基于注解的緩存
對于緩存聲明,spring的緩存提供了一組java注解:
- @Cacheable:觸發緩存寫入。
- @CacheEvict:觸發緩存清除。
- @CachePut:更新緩存(不會影響到方法的運行)。
- @Caching:重新組合要應用于方法的多個緩存操作。
- @CacheConfig:設置類級別上共享的一些常見緩存設置。
@Cacheable注解
顧名思義,@Cacheable可以用來進行緩存的寫入,將結果存儲在緩存中,以便于在后續調用的時候可以直接返回緩存中的值,而不必再執行實際的方法。 最簡單的使用方式,注解名稱=緩存名稱,使用例子如下:
@Cacheable("books")public Book findBook(ISBN isbn) {...}一個方法可以對應兩個緩存名稱,如下:
@Cacheable({"books", "isbns"})public Book findBook(ISBN isbn) {...}?@Cacheable的緩存名稱是可以配置動態參數的,比如選擇傳入的參數,如下: (以下示例是使用SpEL聲明,如果您不熟悉SpEL,可以閱讀Spring Expression Language)
@Cacheable(cacheNames="books", key="#isbn")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)@Cacheable(cacheNames="books", key="#isbn.rawNumber")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)?@Cacheable還可以設置根據條件判斷是否需要緩存
- condition:取決于給定的參數是否滿足條件
- unless:取決于返回值是否滿足條件
以下是一個簡單的例子:
@Cacheable(cacheNames="book", condition="#name.length() < 32") public Book findBook(String name)@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback") public Book findBook(String name)?@Cacheable還可以設置:keyGenerator(指定key自動生成方法),cacheManager(指定使用的緩存管理),cacheResolver(指定使用緩存的解析器)等,這些參數比較適合全局設置,這里就不多做介紹了。
@CachePut注解
@CachePut:當需要更新緩存而不干擾方法的運行時 ,可以使用該注解。也就是說,始終執行該方法,并將結果放入緩存,注解參數與@Cacheable相同。 以下是一個簡單的例子:
@CachePut(cacheNames="book", key="#isbn")public Book updateBook(ISBN isbn, BookDescriptor descriptor)?通常強烈建議不要對同一方法同時使用@CachePut和@Cacheable注解,因為它們具有不同的行為。可能會產生不可思議的BUG哦。
@CacheEvict注解
@CacheEvict:刪除緩存的注解,這對刪除舊的數據和無用的數據是非常有用的。這里還多了一個參數(allEntries),設置allEntries=true時,可以對整個條目進行批量刪除。 以下是個簡單的例子:
@Caching注解 @CacheEvict(cacheNames="books") public void loadBooks(InputStream batch)//對cacheNames進行批量刪除@CacheEvict(cacheNames="books", allEntries=true) public void loadBooks(InputStream batch)?@Caching:在使用緩存的時候,有可能會同時進行更新和刪除,會出現同時使用多個注解的情況.而@Caching可以實現。 以下是個簡單的例子:
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })public Book importBooks(String deposit, Date date)?@CacheConfig注解
@CacheConfig:緩存提供了許多的注解選項,但是有一些公用的操作,我們可以使用@CacheConfig在類上進行全局設置。 以下是個簡單的例子:
@CacheConfig("books") public class BookRepositoryImpl implements BookRepository {@Cacheablepublic Book findBook(ISBN isbn) {...}}?可以共享緩存名稱,統一配置KeyGenerator,CacheManager,CacheResolver。
實例
來看看我們在springboot中怎么使用redis來作為緩存吧.
為spring cache配置redis作為緩存
1.在pom.xml引入redis依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>?2.springboot集成redis配置文件(在本地啟動的redis),在springboot中使用redis,只要配置文件寫有redis配置,代碼就可以直接使用了。
spring:redis:database: 0 # Database index used by the connection factory.url: redis://user:@127.0.0.1:6379 # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password@example.com:6379host: 127.0.0.1 # Redis server host.password: # Login password of the redis server.port: 6379 # Redis server port.ssl: false # Whether to enable SSL support.timeout: 5000 # Connection timeout.?3.redis緩存配置類CacheConfig,這里對spring的緩存進行了配置,包括KeyGenerator,CacheResolver,CacheErrorHandler,CacheManager,還有redis序列化方式。
/*** @author wwj*/ @Configuration public class CacheConfig extends CachingConfigurerSupport {@Resourceprivate RedisConnectionFactory factory;/*** 自定義生成redis-key** @return*/@Override@Beanpublic KeyGenerator keyGenerator() {return (o, method, objects) -> {StringBuilder sb = new StringBuilder();sb.append(o.getClass().getName()).append(".");sb.append(method.getName()).append(".");for (Object obj : objects) {sb.append(obj.toString());}System.out.println("keyGenerator=" + sb.toString());return sb.toString();};}@Beanpublic RedisTemplate<Object, Object> redisTemplate() {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(factory);GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);return redisTemplate;}@Bean@Overridepublic CacheResolver cacheResolver() {return new SimpleCacheResolver(cacheManager());}@Bean@Overridepublic CacheErrorHandler errorHandler() {// 用于捕獲從Cache中進行CRUD時的異常的回調處理器。return new SimpleCacheErrorHandler();}@Bean@Overridepublic CacheManager cacheManager() {RedisCacheConfiguration cacheConfiguration =defaultCacheConfig().disableCachingNullValues().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();} }?代碼使用
測試@Cacheable方法
@Testpublic void findUserTest() {for (int i = 0; i < 3; i++) {System.out.println("第" + i + "次");User user = userService.findUser();System.out.println(user);}}@Override@Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'")public User findUser() {System.out.println("執行方法...");return new User("id1", "張三", "深圳", "1234567", 18);}?執行結果
只有一次輸出了'執行方法...',后面直接從緩存獲取,不會再進入方法。
第0次 執行方法... User{id='id1', name='張三', address='深圳', tel='1234567', age=18} 第1次 User{id='id1', name='張三', address='深圳', tel='1234567', age=18} 第2次 User{id='id1', name='張三', address='深圳', tel='1234567', age=18}?
測試@CachePut方法:對緩存進行了修改
@Testpublic void updateUserTest() {userService.updateUser();User user = userService.findUser();System.out.println(user);}@Override@CachePut(value = "valueName", key = "'keyName1'")public User updateUser() {System.out.println("更新用戶...");return new User("id1", "李四", "北京", "1234567", 18);}?執行結果
對緩存進行了更新,獲取值的時候取了新的值
更新用戶... User{id='id1', name='李四', address='北京', tel='1234567', age=18}?
?
測試@CacheEvict方法:緩存被清空,再次findUser的時候又重新執行了方法。
@Testpublic void clearUserTest() {userService.clearUser();User user = userService.findUser();System.out.println(user);}@Override@CacheEvict(value = "valueName",allEntries = true)public void clearUser() {System.out.println("清除緩存...");}?執行結果
這里清除了緩存,為什么還是沒有執行方法呢?因為這個方法我們定了兩個value值,清了一個還有一個
清除緩存... User{id='id1', name='張三', address='深圳', tel='1234567', age=18}?
最后貼一下代碼吧
User.java
package com.wwj.springboot.model;import java.io.Serializable;/*** @author wwj*/ public class User implements Serializable {public User() {}private String id;private String name;private String address;private String tel;private Integer age;//省略get,set,tostring }CacheTest.java
package com.wwj.springboot.cache;import com.wwj.springboot.model.User; import com.wwj.springboot.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cache.annotation.EnableCaching; import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource;/*** @author wwj*/ @RunWith(SpringRunner.class) @SpringBootTest @EnableCaching public class CacheTest {@Resourceprivate UserService userService;@Testpublic void findUserTest() {for (int i = 0; i < 3; i++) {System.out.println("第" + i + "次");User user = userService.findUser();System.out.println(user);}}@Testpublic void updateUserTest() {userService.updateUser();User user = userService.findUser();System.out.println(user);}@Testpublic void clearUserTest() {userService.clearUser();User user = userService.findUser();System.out.println(user);}}UserService.java
package com.wwj.springboot.service;import com.wwj.springboot.model.User;import java.util.List;/*** @author wwj*/ public interface UserService {/*** 獲取用戶* @return user*/User findUser();/*** 更新用戶信息* @return user*/User updateUser();/*** 清除緩存的用戶信息*/void clearUser();}UserServiceImpl.java
package com.wwj.springboot.service.impl;import com.wwj.springboot.model.User; import com.wwj.springboot.service.UserService; 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;/*** @author wwj*/ @Service @CacheConfig(cacheNames = "CacheConfigName") public class UserServiceImpl implements UserService {@Override@Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'")public User findUser() {System.out.println("執行方法...");return new User("id1", "張三", "深圳", "1234567", 18);}@Override@CachePut(value = "valueName", key = "'keyName1'")public User updateUser() {System.out.println("更新用戶...");return new User("id1", "李四", "北京", "1234567", 18);}@Override@CacheEvict(value = "valueName",allEntries = true)public void clearUser() {System.out.println("清除緩存...");}}?
總結
以上是生活随笔為你收集整理的springboot整合spring @Cache和Redis的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于电脑中的硬盘分区如何合并的问题解决电
- 下一篇: MySQL - InnoDB特性 - B