Spring Boot中使用快取Redis、EhCache
快取相信各位同學都或多或少用到過,畢竟不能把所有壓力都給資料庫。今天來簡單總結一下下在Spring Boot中使用Redis和EhCache快取O(∩_∩)O~
Spring Boot本身是支援多種快取實現的,其中提供了4個註解來幫助大家使用快取:
- @EnableCaching 開啟快取支援
- @Cacheable 先檢查快取是否存在,若存在,則直接返回快取中結果;若不存在,則執行方法獲取結果,並將結果放到快取中
- @CacheEvict 清除快取
- @CachePut 始終執行方法,並將結果放到快取中
先說一下EhCache,EhCache是在記憶體中的快取,也就是說,程式在,快取就在,程式停了,快取就沒了,要使用EhCache,首先引入pom starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在啟動類上開啟快取支援:
@SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
下來只需要在方法上加上註解就行了:
@Cacheable(value="user",key = "#user.id")
public User findOne(User user) {
User u=userRepository.findOne(user.getId());
return u;
}
可以看到,在註解中指定了value和key兩個引數,value是用來歸類用的,以上方法所生成的所有快取在快取庫中都存放在user資料夾下;key是用來指定快取鍵值的,它有兩種生成策略——預設策略和自定義策略,其預設策略如下:
- 如果方法沒有引數,則使用0作為key
- 如果只有一個引數,則使用該引數作為key
- 如果引數多於一個,則使用所有引數的hashCode作為key
很明顯,我這裡自定義了key,指定為引數user物件的id。
key支援通過Sping EL表示式來指定,幾個一看就懂的栗子:
@Cacheable(value="user", key="#id")
public User find(Integer id) {
return null;
}
@Cacheable(value="user", key="#p0")
public User find(Integer id) {
return null;
}
@Cacheable(value="user", key="#user.id")
public User find(User user) {
return null;
}
@Cacheable(value="user", key="#p0.id")
public User find(User user) {
return null;
}
除了上述使用方法引數生成key以外,Spring還提供了一個root物件來生成key:
屬性名稱 | 描述 | 示例 |
---|---|---|
methodName | 當前方法名 | #root.methodName |
target | 當前被呼叫的物件 | #root.target |
targetClass | 當前被呼叫的物件的class | #root.targetClass |
args | 當前方法引數組成的陣列 | #root.args[0] |
caches | 當前被呼叫的方法使用的Cache | #root.caches[0].name |
另外,如果EhCache有別的設定,那麼可以新建一個ehcache.xml,在application.properties中配好這個配置檔案即可:
spring.cache.type=ehcache
spring.cache.ehcache.config=static/ehcache.xml
下面說一下Redis,同樣首先引入pom starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
同樣通過@EnableCaching開啟快取支援。
由於Redis是獨立安裝的,它就像資料庫一樣可以持久化資料,所以必然也像資料庫一樣有連線地址,在application.yml中配置如下:
spring:
redis:
database: 0
host: 10.155.20.162
port: 6379
pool:
max-active: 80
max-wait: -1
max-idle: 80
min-idle: 0
timeout: 5000
吶,EhCache的時候用的properties配置檔案,Redis用的yml配置檔案喲,各取所愛吧~
同樣在方法上面使用@Cacheable、@CacheEvict、@CachePut來操作快取。
這裡介紹一下keyGenerator,前面key的生成策略就是它控制的,Spring允許我們自定義這個Generator,舉個栗子:
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
//自定義key生成方式
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
String[] value = new String[1];
Cacheable cacheable = method.getAnnotation(Cacheable.class);
if (cacheable != null) {
value = cacheable.value();
}
CachePut cachePut = method.getAnnotation(CachePut.class);
if (cachePut != null) {
value = cachePut.value();
}
CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class);
if (cacheEvict != null) {
value = cacheEvict.value();
}
sb.append(value[0]);
sb.append(":");
sb.append(params[0].toString());
return sb.toString();
}
};
}
//快取管理器
@Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(43200); //設定快取過期時間
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
StringRedisTemplate template = new StringRedisTemplate(factory);
@SuppressWarnings({ "rawtypes", "unchecked" })
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
可以看到,這個Config中有3個Bean,第1個Bean中用註解的value屬性+":"+第一個引數作為key值的生成策略;第2個Bean中指定了快取的全域性過期時間;第3個Bean中定義了RedisTemplate。
ok,以上講了通過註解來操作快取,不過有的時候,並不一定存在方法,只是單純地想操作某個key值的快取,咋辦?這個時候就要用到RedisTemplate啦,Spring中自帶這個物件,包括上面也自定義了這個物件,我們在需要使用的地方把它注入進來就可以了。不過,通常我們會先寫個工具類:
@Service
public class RedisService {
@Autowired
@Qualifier("stringRedisTemplate")
RedisTemplate template;
public void setValue(String key, Object val) {
template.opsForValue().set(key, val);
}
public void setValue(String key, Object val, int time, TimeUnit unit) {
template.opsForValue().set(key, val, time, unit);
}
public Object getValue(String key) {
return template.opsForValue().get(key);
}
public void deleteValue(String key){
template.delete(key);
}
}
可以看到,我這邊使用的是stringRedisTemplate,具體還有什麼其它型別,各位同學自己去發現一以下吧~