- SpringCache缓存框架
- 简介
- 使用
- 加入依赖
- 配置文件
- SpringCache常用注解
- @Cacheable
- @CachePut
- @CacheEvict
- @Caching
- @CacheConfig
- SpringBoot+MyBatisPlus+H2+SpringCache+Redis整合使用
- 依赖引入
- h2,初始化SQL脚本
- yml配置
- 主启动类
- CacheConfig类
- KeyGenerator
- Entity类
- Mapper
- Service
- Controller
- 官方地址https://spring.io/guides/gs/caching/
- 提供基本的Cache抽象,方便切换各种底层Cache,如Redis,caffeine
- 提供类似@Transactional注解事务的方式,类实现Cache
- 提供事务回滚时自动回滚缓存
- 核心
- Cache接口,缓存操作的API
- CacheManager管理各类缓存,有多个缓存框架的实现
配置文件org.springframework.boot spring-boot-starter-cache 2.5.3
选择缓存类型
spring:
cache:
type: redis
SpringBoot启动类开启缓存注解
@EnableCachingSpringCache常用注解 @Cacheable
- value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了
- key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = “#p0”):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档
- 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接口来实现自己的缓存解析器,并用该参数指定。
@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
@CacheEvict@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空,主要用作删除
@Caching有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user) {
}
@CacheConfig
所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。
@CacheConfig是一个类级别的注解
SpringBoot+MyBatisPlus+H2+SpringCache+Redis整合使用 依赖引入h2,初始化SQL脚本org.springframework.boot spring-boot-starter-parent 2.5.3 org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-cache 2.5.3 org.springframework.boot spring-boot-starter-web com.baomidou mybatis-plus-boot-starter 3.4.3.4 com.h2database h2 runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
data-h2.sql
DELETe FROM user; INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com'); INSERT INTO user2 (id, name, age) VALUES (1, 'Jone', 18), (2, 'Jack', 20), (3, 'Tom', 28), (4, 'Sandy', 21), (5, 'Billie', 24);
schema-h2.sql
DROp TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) ); CREATE TABLE user2 ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', PRIMARY KEY (id) );yml配置
spring:
cache:
type: redis
#H2配置
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test
username: root
password: test
#H2初始化
sql:
init:
#表结构
schema-locations: classpath:db/schema-h2.sql
#表数据
data-locations: classpath:db/data-h2.sql
redis:
host: Redis地址
password: Redis密码
database: 0
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
主启动类
@SpringBootApplication
@MapperScan("com.peppa.springcache.mapper")
@ComponentScan("com.peppa")
@EnableCaching
public class SpringCacheTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheTestApplication.class, args);
}
}
CacheConfig类
其中配置了RedisCacheManager
@Configuration
public class CacheConfig {
@Bean
@Primary
public RedisCacheManager cacheManager1Hour(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration config=instanceConfig(3600L);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
@Bean
public RedisCacheManager cacheManager1Min(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration config=instanceConfig(60L);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
private RedisCacheConfiguration instanceConfig(Long ttl){
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
//去掉各种@JsonSerialize的注解的解析
objectMapper.configure(MapperFeature.USE_ANNOTATIONS,false);
//只针对非空值进行序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//将类型序列化到属性json字符串中
objectMapper.activateDefaultTyping(LaissezFaireSubTypevalidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl))
.disableCachingNullValues()
.serializevaluesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
}
}
@Bean
public KeyGenerator springCacheCustomeKeyGenerator(){
return new KeyGenerator(){
@override
public Object generate(Object o,Method method,Object... objects){
retrun o.getClass().getSimpleName()+"_"
+method.getName()+"_"
+ StringUtils.arrayToDelimitedString(objects,"_");
}
}
}
KeyGenerator
Entity类
User
@Data
@Builder
//一定要序列化,Redis存储必须序列化实体类
public class User implements Serializable {
private Long id;
private String name;
private Integer age;
private String email;
}
Mapper
@Mapper public interface UserMapper extends baseMapperService{ }
@Service
public class UserService {
@Autowired
UserMapper userMapper;
@Cacheable(value = {"user"},key = "#root.methodName",cacheManager = "cacheManager1Min")
public List select(){
List users = userMapper.selectList(null);
return users;
}
@CachePut(value = {"user"},key = "#root.args[0]")
public User insert(Long id){
User user = User.builder().id(id).build();
int insert = userMapper.insert(user);
return user;
}
@Cacheable(value = {"user"},keyGenerator="springCacheCustomeKeyGenerator")
public User selectOne(Long id){
User user = userMapper.selectById(id);
return user;
}
@CacheEvict(value = {"user"},key = "#root.args[0]")
public int delete(Long id){
int insert = userMapper.deleteById(id);
return insert;
}
}
Controller


