1、SpringCache是spring3.1版本发布出来的,它是对使用缓存进行封装和抽象,通过在方法上使用annotation注解来拿到缓存结果。正因为用了annotation,所以它解决了业务代码和缓存代码的耦合度问题,即在不侵入业务代码的基础上让现有代码即刻支持缓存
注:对于redis的缓存,SpringCache只支持string,其他的hash、list、set、zset都不支持,要特别注意
2、pom文件添加配置
<!-- springcache缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
3、添加springcache的redis配置类
在包com.example.config下,添加SpringCacheRedisConfig.java
package com.example.config;
import java.time.Duration;
import org.springframework.cache.CacheManager;
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.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching //启动SpringCache缓存
public class SpringCacheRedisConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration
//设置缓存的默认超时时间:30分钟
.entryTtl(Duration.ofMinutes(30L))
//如果是空值,不缓存
.disableCachingNullValues()
//设置key序列化器
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
//设置value序列化器
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration)
.build();
}
}
4、建立测试Controller
在包com.example.web下,添加SpringCacheController.java
package com.example.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.create.entity.TblTeacherInf;
import com.example.service.SpringCacheService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Api(description = "springcache测试接口")
@RestController
@RequestMapping("/springcache")
public class SpringCacheController {
@Autowired
SpringCacheService springCacheService;
@ApiOperation("增加一条记录")
@GetMapping("/insert")
public TblTeacherInf insert(TblTeacherInf teacher) {
return springCacheService.insert(teacher);
}
@ApiOperation("修改一条记录")
@GetMapping("/update")
public TblTeacherInf update(TblTeacherInf teacher) {
return springCacheService.update(teacher);
}
@ApiOperation("删除一条记录")
@GetMapping("/delete")
public boolean delete(TblTeacherInf teacher) {
return springCacheService.delete(teacher);
}
@ApiOperation("查找一条记录")
@GetMapping("/findById")
public TblTeacherInf findById(Integer id) {
return springCacheService.findById(id);
}
}
5、建立测试Service
在包com.example.service下,添加SpringCacheService.java
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
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 com.create.entity.TblTeacherInf;
import com.create.entity.TblTeacherInfMapper;
@Service
@CacheConfig(cacheNames = {"redis-cache"})
public class SpringCacheService {
@Autowired
TblTeacherInfMapper teacherMapper;
/**
* 增加
*
* @param teacher
* @return
*/
@Cacheable(key = "#teacher.id")
public TblTeacherInf insert(TblTeacherInf teacher) {
// 先插入数据库
teacherMapper.insert(teacher);
// 再查询出插入的对象
return teacherMapper.selectByPrimaryKey(teacher.getId());
}
/**
* 修改
*
* @param teacher
* @return
*/
@CachePut(key = "#teacher.id")
public TblTeacherInf update(TblTeacherInf teacher) {
// 先修改数据库
teacherMapper.updateByPrimaryKeySelective(teacher);
// 再查询出修改的对象
return teacherMapper.selectByPrimaryKey(teacher.getId());
}
/**
* 删除
*
* @param teacher
* @return
*/
@CacheEvict(key = "#teacher.id")
public boolean delete(TblTeacherInf teacher) {
// 先删除数据库
teacherMapper.deleteByPrimaryKey(teacher.getId());
return true;
}
/**
* 查找
*
* @param id
* @return
*/
@Cacheable(key = "#id")
public TblTeacherInf findById(Integer id) {
return teacherMapper.selectByPrimaryKey(id);
}
}
6、注解说明
1)@CacheConfig
作用在类上,统一该类所有缓存key的前缀
这里所有缓存key的前缀为redis-cache::,两个冒号是自动加的
2)@Cacheable
作用在方法上,用于将方法的结果缓存起来
方法调用时,先从缓存中读取key,如果缓存中没有,则查询数据库,再添加到缓存中
3)@CachePut
作用在方法上,用于更新缓存
方法调用时,先执行方法体,然后通过返回值更新缓存,key为redis-cache::加上teacher.id的值
4)@CacheEvict
作用在方法上,用于删除缓存
方法调用时,先执行方法体,然后根据key删除缓存
7、测试
访问swagger测试页面:http://127.0.0.1:8088/swagger-ui.html
8、redisTemplate和SpringCache缓存的区别
1)用redisTemplate手动缓存
key为redis-cache:1,TTL为-1,json串为{"@class":"com.create.entity.TblTeacherInf","id":1,"name":"刘备"}
2)用SpringCache自动缓存
key为redis-cache::2,TTL为1255(自动减少),json串为{"@class":"com.create.entity.TblTeacherInf","id":2,"name":"张飞"}
3)对于redis的缓存,SpringCache只支持string,其他的hash、list、set、zset都不支持,所以对于hash、list、set、zset只能用redisTemplate
4)对于多表查询的数据缓存,SpringCache是不支持的,只支持单表的简单缓存
5)SpringCache缓存过期时间不会自动更新
更新同一个key后,它的有效期在redis里并没有恢复。一个key初始为30分钟有效,过了10分钟更新了它的值,有效期仍旧为20分钟
注:最新代码上传至https://github.com/csj50/myboot