Springboot高级(一)缓存

一、缓存结构

Springboot高级(一)缓存_第1张图片

二、注解

Springboot高级(一)缓存_第2张图片

三、体验缓存

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 异步

Springboot高级(一)缓存_第3张图片

运行流程:
@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() {
            @Override
            public 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.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

2、配置

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

3、整合

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

    @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);
        }
    }

(2)缓存实体


	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);
    }
注意: 如此缓存,序列化会出问题(转义)

Springboot高级(一)缓存_第4张图片

进行优化- -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);
    }

Springboot高级(一)缓存_第5张图片

4、原理

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

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

你可能感兴趣的:(SpringBoot,spring,boot,缓存,java)