1、安装依赖
<!--spring-boot-starter-data-redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring cache-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、配置文件
spring:
cache:
type: redis
redis:
time-to-live: 3600000
key-prefix: CACHE_
use-key-prefix: true
cache-null-values: true
redis:
database: 4
host: localhost
port: 6379
password: 1234abcd
3、配置文件类
package com.example.springbootclickhouse.config;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@EnableConfigurationProperties(CacheProperties.class)//开启属性绑定配置的功能
@Configuration //配置类
@EnableCaching //开启缓存功能
public class SpringCacheConfig {
//第二种、因为注入了容器,参数属性spring会自己去容器里面找 (CacheProperties cacheProperties)
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config= config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
/**
* GenericFastJsonRedisSerializer fastjson家族的
* GenericJackson2JsonRedisSerializer spring自带的 package org.springframework.data.redis.serializer;
*/
//指定序列化-Jackson
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
//指定序列化-fastjson
//config= config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()));
//从所以配置中取出redis的配置
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
//将配置文件中所有的配置都生效(之间从源码里面拷 RedisCacheConfiguration)
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config=config.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
4、定义业务接口和实现类
4.1、实体类
package com.example.springbootclickhouse.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
Integer age;
}
4.2、业务接口
package com.example.springbootclickhouse.service;
import com.example.springbootclickhouse.entity.User;
import java.util.List;
public interface IUserService {
List<User> getUserList(String userName);
String deleteUserByName(String userName);
List<User> updateUser(List<User> list);
}
4.3、实现类
package com.example.springbootclickhouse.service.impl;
import com.example.springbootclickhouse.entity.User;
import com.example.springbootclickhouse.service.IUserService;
import lombok.SneakyThrows;
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;
import java.util.ArrayList;
import java.util.List;
@Service
@CacheConfig(cacheNames = "User")//指定缓存空间的名称
public class UserServiceImpl implements IUserService {
//查询带缓存
@Override
@Cacheable(key = "#userName",sync = true)
@SneakyThrows
public List<User> getUserList(String userName){
Thread.sleep(5000);
List<User> list=new ArrayList<>();
list.add(new User(1l,"xxx",28));
list.add(new User(2l,"xxxx",28));
list.add(new User(3l,"xxx",28));
return list;
}
//删除
@Override
@CacheEvict(key = "#userName")
public String deleteUserByName(String userName){
return "OK";
}
//更新
@Override
@CachePut(key = "'xxxx'")
public List<User> updateUser(List<User> list){
return list;
}
}
5、注解详情
5.1、注解
@Cacheable 触发将数据保存到缓存的操作(启动缓存)
@CacheEvict 触发将数据从缓存删除的操纵(失效模式)
@CachePut 不影响方法执行更新缓存(双写模式)
@Caching 组合以上多个操作(点击注解看源码就知道了,组合注解))
@CacheConfig 在类级别共享缓存的相同配置
5.2、@Cacheable注解
value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了
key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = “#p0”):使用函数第一个参数作为缓存的key值
condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = “#p0”, condition = “#p0.length() < 3”),表示只有当第一个参数的长度小于3的时候才会被缓存
unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的
cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。