前面讲了【第二章】SpringBoot2.x集成Redis , 以及SpringBoot中redis的基本使用.
本篇主要讲Redis数据库作为SpringBoot中缓存(Cache)的基本使用.
引入依赖
<!-- redis starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce pool 缓存连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
不再需要引入其他依赖,SpringBoot导入spring-boot-starter-data-redis时,
CacheManager默认使用RedisCache.
如果项目不是以Redis作为缓存,则需引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
application.yml配置
spring:
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器连接端口
port: 6379
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接密码(默认为空)
password: 123456
# 连接超时时间(毫秒)
timeout: 5000
lettuce:
# 关闭超时时间
shutdown-timeout: 100
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 10000
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
开启缓存@EnableCaching, 并配置CacheManager,KeyGenerator
- @EnableCaching: 开启缓存
- CacheManager: Spring缓存管理器
- KeyGenerator: Redis 缓存键生成策略, Spring 默认的DefaultKeyGenerator根据参数列表生成Key,当参数列表的值相同时是一样的 就会造成获取到错误的缓存数据
import com.alibaba.fastjson.JSONObject;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.StringJoiner;
/**
* @Title: RedisCacheConfig
* @Description: TODO(reids缓存配置)
* @Author flyingkid
* @Date 2019/6/5下午 11:36
*/
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
/**
* @description TODO 缓存key前缀
*/
private static final String keyPrefix = "CACHE:";
/**
* 缓存生成key的策略
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringJoiner joiner = new StringJoiner(":",keyPrefix,"");
joiner.add(target.getClass().getSimpleName());
joiner.add(method.getName());
for (Object param : params) {
joiner.add(JSONObject.toJSONString(param));
}
return joiner.toString();
};
}
/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(keySerializer());
redisTemplate.setHashKeySerializer(keySerializer());
redisTemplate.setValueSerializer(valueSerializer());
redisTemplate.setHashValueSerializer(valueSerializer());
return redisTemplate;
}
/**
* 管理缓存
*/
@Bean
@Primary
public CacheManager cacheManager(LettuceConnectionFactory factory){
//缓存配置对象
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
//设置缓存的默认超时时间:30分钟
.entryTtl(Duration.ofMinutes(30L))
//如果是空值,不缓存
.disableCachingNullValues()
//设置key序列化器
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
//设置value序列化器
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
.cacheDefaults(cacheConfig).build();
}
/**
* key序列化
*/
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
/**
* value序列化
*/
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
注: StringJoiner是 java8对String字符串拼接提供的工具类, new StringJoiner(":",keyPrefix,"");
构造器第一个参数表示拼接以冒号分隔,参数二是前缀,参数三是后缀. 感兴趣的小伙伴可以阅读下java.util.StringJoiner源码.
缓存基本使用
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* @ClassName: ExampleService
* @Description: TODO redis缓存
* @Author: 爱飘de小子
*/
@Slf4j
@Service
@CacheConfig(keyGenerator = "keyGenerator") //这是本类统一key生成策略
public class ExampleService {
/**
* @description TODO 添加缓存
* @param name
*/
@Override
@Cacheable(value = "addCache")
public String addCache(String name) {
return "爱飘de小子";
}
/**
* @description TODO 删除缓存
* @param name
*/
@Override
@CacheEvict(value = "addCache",allEntries=true)
public void delCache(String name) {
}
}
缓存注解详解
@Cacheable
添加在方法上,根据条件添加缓存
- value: 缓存的名称,不能为空
- cacheNames: 缓存的名称,和value二选一
- key: 缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
- keyGenerator: 指定key的生成策略
- cacheManager: 指定缓存管理器
- cacheResolver: 指定获取解析器
- condition: 条件符合则缓存
- unless: 条件符合则不缓存
- sync: 是否使用异步模式 默认false
@CachePut
添加在方法上,根据条件添加缓存
@CachePut作用和@Cacheable类似,区别是@Cacheable没有缓存数据会执行方法后,把结果缓存起来,第二次调用方法不执行方法,直接从缓存中获取数据并返回.
@CachePut每次都会执行方法,不管缓存中有没有数据,都会把结果缓存.
@CacheEvict
添加在方法上,根据条件清空缓存.
- value: 缓存名称,不能为空
- cacheNames: 缓存的名称,与value二选一
- keyGenerator: key的生成器。key/keyGenerator二选一使用
- condition: 触发条件,支持SpEL
- allEntries: true表示清除value中的全部缓存,默认为false
- beforeInvocation: 是否在方法执行前就清空 默认false
- cacheManager: 指定缓存管理器
- cacheResolver: 或者指定获取解析器
@CacheConfig
作用在类上,为本类的缓存注解配置全局属性
- cacheNames: 缓存名称
- keyGenerator: key的生成器
- cacheManager: 缓存管理器
- cacheResolver: 获取解析器
@Caching
组合多个缓存注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
Caching注解中Cacheable,CachePut,CacheEvict都是数组类型. 可以满足方法添加或者删除多个缓存.