> 文章列表 > Springboot高级(一)缓存

Springboot高级(一)缓存

Springboot高级(一)缓存

一、缓存结构

在这里插入图片描述

二、注解

在这里插入图片描述

三、体验缓存

1、开启缓存 @EnableCaching

@SpringBootApplication
@EnableCaching
public class SpringbootCacheApplication {

2、标志注解

(1)Cacheable

	@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:

  1. 方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
    (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建
  2. 去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
    key是按照某种策略生成的:默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成keyi
    SimpleKeyGenerator生成key的默认策略;
    如果没有参数;key=new SimpleKey();
    如果有一个参数:key=参数的值
    如果有多个参数:key=new SimpleKey(params);
  3. 没有查到缓存就调用目标方法;
  4. 将目标方法返回的结果,放进缓存中

@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() {@Overridepublic Object generate(Object target, Method method, Object... objects) {return method.getName() + '[' + Arrays.asList(objects).toString() + ']';}};}
}

(2)@CachePut

既调用方法,又更新缓存,实现同步缓存。
先调用方法,再将结果缓存起来。

    @CachePut(value = "emp", key = "#entity.id")public Employee edit(Employee entity){employeeMapper.updateEmp(entity);return entity;}

测试步骤:

  1. 先查询1号员工,放入缓存中

  2. 更新1号员工

  3. 再次查询

    注:@CachePut和@Cacheable的key值必须一样,例如:查询的#id和更新的#entity.id都代表1
    

(3)@CacheEvict

@CacheEvict(value = "emp", key = "#id")public void remove(Integer id){System.err.println("删除的id" + id);employeeMapper.deleteEmpById(id);}
allEntries = true   // 删除所以缓存
beforeInvocation = true   //true在方法之前清除缓存,false在方法之后清除缓存

(4)@Caching 复杂注解

	@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查询缓存

(5)@CacheConfig

类上公共配置

@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {

四、整合Redis

1、引入

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

2、配置

spring.redis.port=6379
spring.redis.host=127.0.0.1

3、整合

(1)对Redis五种基本类型的操作

    @AutowiredRedisTemplate redisTemplate;@AutowiredStringRedisTemplate stringRedisTemplate;@Testvoid test01(){//操作String类型stringRedisTemplate.opsForValue();//操作List类型stringRedisTemplate.opsForList();//操作set类型stringRedisTemplate.opsForSet();//操作hash类型stringRedisTemplate.opsForHash();//操作Zset类型stringRedisTemplate.opsForZSet();redisTemplate.opsForValue();}
	//向redis中缓存msg@Testvoid test01(){stringRedisTemplate.opsForValue().append("msg", "第一个消息");stringRedisTemplate.opsForList().leftPush("nameList", "张三");stringRedisTemplate.opsForList().leftPush("nameList", "李四");stringRedisTemplate.opsForList().leftPush("nameList", "allen");}//从redis中获取缓存msg@Testvoid 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);}}

(2)缓存实体

public class Employee implements Serializable {....}@Testvoid  test03(){Employee entity = new Employee();entity.setId(1);entity.setName("小明");entity.setPassword("123456");redisTemplate.opsForValue().set("emp.01", entity);}
注意: 如此缓存,序列化会出问题(转义)

Springboot高级(一)缓存

进行优化- -JSON格式化

@Configuration
public class MyRedisTemplate {@Beanpublic 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;}
}
    @Testvoid  test03(){Employee entity = new Employee();entity.setId(2);entity.setName("小红");entity.setPassword("123456");empRedisTemplate.opsForValue().set("emp.02", entity);}

Springboot高级(一)缓存

4、原理

缓存注解还是原先的,只是改变了CahceManager

1、引入redis的starter,容器中保存的是RedisCacheManager;
2、RedisCacheManager帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据
3、默认保存数据 k-v 都是Object;利用序列化保存,使用jdk的序列化机制
4、自定义CacheManager
Springboot高级(一)缓存