@SpringBootApplication
@EnableCaching
public class SpringbootCacheApplication {
@Cacheable(value = "emp", condition ="#id==2",
unless = "#result == null")
public Employee getEmpById(Integer id) {
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
注意:Springboot2.X版本以上必须添加value属性
属性 | 作用 |
---|---|
value | 指定缓存的名字 |
cacheNames | 指定缓存的名字 |
key | 缓存数据时的key(默认使用参数,SpEL表达式) |
keyGenerator | key的生成器 |
cacheManager | 缓存管理器 |
condition | 指定符合条件才缓存 |
unless | 除非 |
sync | 异步 |
运行流程:
@Cacheable:
@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;
核心:
1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator
指定自己的keyGenerator
@Cacheable(value = "emp", keyGenerator = "myKeyGenerator")
@Configuration
public class KeyGeneratorConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... objects) {
return method.getName() + '[' + Arrays.asList(objects).toString() + ']';
}
};
}
}
既调用方法,又更新缓存,实现同步缓存。
先调用方法,再将结果缓存起来。
@CachePut(value = "emp", key = "#entity.id")
public Employee edit(Employee entity){
employeeMapper.updateEmp(entity);
return entity;
}
测试步骤:
先查询1号员工,放入缓存中
更新1号员工
再次查询
注:@CachePut和@Cacheable的key值必须一样,例如:查询的#id和更新的#entity.id都代表1
@CacheEvict(value = "emp", key = "#id")
public void remove(Integer id){
System.err.println("删除的id" + id);
employeeMapper.deleteEmpById(id);
}
allEntries = true // 删除所以缓存
beforeInvocation = true //true在方法之前清除缓存,false在方法之后清除缓存
@Caching(
cacheable = { @Cacheable(value = "emp", key = "#lastName")},
put = {
@CachePut(value = "emp", key = "#result.id"),
@CachePut(value = "emp", key = "#result.email")
}
)
public Employee getByLastName(String lastName) {
return employeeMapper.getByLastName(lastName);
}
查询到数据放入到了put缓存中,key通过id和email查询缓存
类上公共配置
@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring.redis.port=6379
spring.redis.host=127.0.0.1
@Autowired
RedisTemplate redisTemplate;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
void test01(){
//操作String类型
stringRedisTemplate.opsForValue();
//操作List类型
stringRedisTemplate.opsForList();
//操作set类型
stringRedisTemplate.opsForSet();
//操作hash类型
stringRedisTemplate.opsForHash();
//操作Zset类型
stringRedisTemplate.opsForZSet();
redisTemplate.opsForValue();
}
//向redis中缓存msg
@Test
void test01(){
stringRedisTemplate.opsForValue().append("msg", "第一个消息");
stringRedisTemplate.opsForList().leftPush("nameList", "张三");
stringRedisTemplate.opsForList().leftPush("nameList", "李四");
stringRedisTemplate.opsForList().leftPush("nameList", "allen");
}
//从redis中获取缓存msg
@Test
void test02(){
String msg = stringRedisTemplate.opsForValue().get("msg");
System.err.println(msg);
List<String> myList = stringRedisTemplate.opsForList().range("nameList", 0, -1);
for (String str : myList) {
System.err.println(str);
}
}
public class Employee implements Serializable {
....
}
@Test
void test03(){
Employee entity = new Employee();
entity.setId(1);
entity.setName("小明");
entity.setPassword("123456");
redisTemplate.opsForValue().set("emp.01", entity);
}
注意: 如此缓存,序列化会出问题(转义)
进行优化- -JSON格式化
@Configuration
public class MyRedisTemplate {
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate
(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Employee> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> serializer =
new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(serializer);
return template;
}
}
@Test
void test03(){
Employee entity = new Employee();
entity.setId(2);
entity.setName("小红");
entity.setPassword("123456");
empRedisTemplate.opsForValue().set("emp.02", entity);
}
缓存注解还是原先的,只是改变了CahceManager
1、引入redis的starter,容器中保存的是RedisCacheManager;
2、RedisCacheManager帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据
3、默认保存数据 k-v 都是Object;利用序列化保存,使用jdk的序列化机制
4、自定义CacheManager