SpringCache的简介
缓存,就是将数据从数据库等数据来源获取数据,将数据缓存在内存或其他设备如Redis中,为了二次查询能够快速高效的响应结果.
Spring Cache是3.1开始提供, 通过注解的形式,对于整合业务代码友好.
Spring Cache特点:
提供Cache通用入口 ,方便多种实现切换缓存源,如Redis,Guava Cache等
支持事务, 即事务回滚时,缓存同时自动回滚
Cache-redis环境搭建
1.依赖配置
<!-- Cache基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- 使用 redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- jackson默认不支持java8的时间类型,需要添加一个时间模块 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.0</version>
</dependency>
2.application配置
#redis
redis:
host: 43.139.54.197
port: 6370
password: '123456'
database: 0
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 1000ms #连接等待时间
debug: true
Cache的注解
@EnableCaching
使用场景:在启动类注解@EnableCaching开启缓存
@SpringBootApplication
@EnableCaching //开启缓存
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Cacheable
使用场景: 查询方法接口
该注解会把方法的返回值缓存下来, 下一次调用方法时, 先查询缓存中是否存在,存在则直接返回,不存在,则查询数据返回,并将数据缓存.
// 先从缓存中读取,如果没有再调用方法获取数据,然后把数据添加到缓存中
@Cacheable(value = "user", key = "#id")
public User select(String id) {
List<User> users = userMapper.selectAll();
for (User user : users) {
if (user.getId().equals(id)) {
return user;
}
}
return null;
}
1.注解属性:
注解属性 | 作用 |
cacheNames | 缓存key前缀名字,设置缓存组件 |
key | 缓存key后缀 |
condition | SpringEL表达式,结果为true,缓存数据到redis。结果为false,不缓存数据到redis |
unless | SpringEL表达式,结果为false,缓存数据到redis。结果为true,不缓存数据到redis |
2.SpEL上下文数据
属性名称 | 描述 | 示例 |
methodName | 当前方法名 | #root.methodName |
method | 当前方法 | #root.method.name |
target | 当前被调用的对象 | #root.target |
targetClass | 当前被调用的对象的class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
caches | 当前被调用的方法使用的Cache | #root.caches[0].name |
@Cacheput
使用场景: 新增或修改方法
该注解会把方法的返回值Put到缓存中, 供其他查询使用,如果有同一缓存则覆盖.
// 查询数据库,将返回结果放到缓存
@CachePut(value = "user", key = "#user.id")
public User save(User user) {
userMapper.insert(user);
return user;
}
@CacheEvict
使用场景: 删除或修改方法
该注解会清空指定缓存.
// 移除对应的缓存
@CacheEvict(value = "user", key = "#user.id")
public User update(User user) {
userMapper.updateByPrimaryKey(user);
return user;
}
@Caching
使用场景: 同时操作多个缓存
该注解是一个组合缓存,可以同时添加几个不同的注解,供不同的应用场景使用.如一个接口,可能同时操作多个缓存,且缓存的处理状态都不一样.
@Caching(
cacheable = {
@Cacheable(value = "user",keyGenerator = "xdclassKeyGenerator")
},
put = {
@CachePut(value = "user",key = "#id"),
@CachePut(value = "user",key = "'stock:'+#id")
}
)
@CacheConfig
该注解用于配置该类中用的一些共用的缓存配置
@CacheConfig(cacheNames = "cache:prefix")
Redis序列化配置类和Cache缓存配置类
@Configuration
public class RedisConfig {
private static StringRedisSerializer stringRedisSerializer;
private static Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer;
static {
//定义string类型序列化对象
stringRedisSerializer = new StringRedisSerializer();
//定义Jackson类型序列化对象
jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
//LocalDateTime序列化异常
om.registerModule(new JavaTimeModule());
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL
, JsonTypeInfo.As.WRAPPER_ARRAY);
jackson2JsonRedisSerializer.setObjectMapper(om);
}
@Bean //Redis序列化配置
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
//配置连接工程
template.setConnectionFactory(factory);
//redis key序列化方式
template.setKeySerializer(stringRedisSerializer);
//redis value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
//hashmap key序列化
template.setHashKeySerializer(stringRedisSerializer);
//hashmap value序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
//Cache配置
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
//过期时间
.entryTtl(Duration.ofSeconds(600))
//缓存key
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
//缓存组件value
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
//value不为空
.disableCachingNullValues()
.computePrefixWith(cacheName -> cacheName + ":");
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
Cache的自定义Key策略组件配置
1.配置
@Component("selfKeyGenerate")
public class SelfKeyGenerate implements KeyGenerator {
public Object generate(Object target, Method method, Object... params) {
if (params.length == 0) {
return SimpleKey.EMPTY;
}
Object param = params[0];
// 参数为map自定义key=类名+方法名+map的key-value值
if (param instanceof Map) {
StringBuilder builder = new StringBuilder();
// 分隔符
String sp = ".";
builder.append(target.getClass().getSimpleName()).append(sp);
builder.append(method.getName()).append(sp);
Map<String, Object> map = (Map<String, Object>) param;
if (map.isEmpty()) {
return builder.toString();
}
for (String key : map.keySet()) {
builder.append(key).append("-").append(map.get(key)).append(sp);
}
// builder.append(IdUtil.randomUUID());
return builder.toString();
}
return new SimpleKey(params);
}
}
2.使用
@Cacheable(cacheNames = "perCenter",keyGenerator = "selfKeyGenerate")
public R PersonalCenter(HttpServletRequest request){
return null;
}