spring boot项目基于redis集成Spring Cache实现缓存
一、环境
1、运行环境
目前场景是springboot项目集成了redis,如果还没有集成redis,建议浏览下面两篇文章 腾讯云服务器安装redis spring boot项目集成redis 2、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
二、编写缓存配置类
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
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.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Configuration
@EnableCaching
public class CacheConfig {
private final static int DEFAULT_EXIRE_TIME = 7200;
@Bean
public KeyGenerator classKey() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
return sb.toString();
};
}
@Bean
public KeyGenerator classMethodKey() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append(method.getName());
return sb.toString();
};
}
@Bean
public KeyGenerator classMethodParamsKey() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append(method.getName());
for (Object obj : params) {
sb.append("#");
sb.append(obj == null ? "" : obj.toString());
}
return sb.toString();
};
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
this.getRedisCacheConfigurationWithTtl(DEFAULT_EXIRE_TIME),
this.getRedisCacheConfigurationMap()
);
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
return redisCacheConfigurationMap;
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new JavaTimeModule());
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
}
三、简单使用
缓存的操作主要有@Cacheable、@CachePut、@CacheEvict 这里以@Cacheable和@CacheEvict的简单使用做个示例
1、@Cacheable
Spring 在执行 @Cacheable 标注的方法前先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,执行该方法并将方法返回值放进缓存。 参数: value 缓存名、 key 缓存键值、 condition 满足缓存条件、unless 否决缓存条件
@Cacheable(value = "student", key = "'com.study.coursehelper.demo.controller.StudentController'")
@RequestMapping("listAll")
@ResponseBody
public Msg listAll(Student student,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "5") int limit) {
log.info("listAll入参: {} page:{} limit:{}",student,page,limit);
Page<Student> studentPage = new Page<>(page,limit);
LambdaQueryWrapper<Student> studentLambdaQueryWrapper = new LambdaQueryWrapper<>();
if(!StringUtils.isEmpty(student.getName())){
studentLambdaQueryWrapper.like(Student::getName,student.getName());
}
IPage<Student> studentIPage = studentService.page(studentPage,studentLambdaQueryWrapper);
Msg result = Msg.okCountData(studentIPage.getTotal(),studentIPage.getRecords());
log.info("listAll出参: {}",result);
return result;
}
在浏览器请求http://localhost:8080/student/listAll  可以看到redis数据库已经存入数据  并且可以看到第一次请求时,查询数据库,之后的请求会直接从缓存中获取,所以控制台只打印了一次sql 
2、@CacheEvict
方法执行成功后会从缓存中移除相应数据。 参数: value 缓存名、 key 缓存键值、 condition 满足缓存条件、 unless 否决缓存条件、 allEntries 是否移除所有数据(设置为true 时会移除所有缓存)
@CacheEvict(value = "student", key = "'com.study.coursehelper.demo.controller.StudentController'")
@RequestMapping("/update")
@ResponseBody
public boolean update(Student student){
log.info("update入参: {}",student);
return studentService.updateById(student);
}
调用该方法后会发现redis数据库中对应的数据被清除了 
|