springBoot缓存操作

一、SprignBoot缓存JSR107简介

1.1 JSR-107

Java Caching定义了5个核心接口

  • CacheingProvider:定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期运行多个CachingProvider
  • CacheManager:定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有
  • Cache:是一个类似Map的数据结构并临时存储以key为索引的值。一个Cache仅被一个CacheManager所拥有。
  • Entry:是一个存储在Cache中的key-value对
  • Expiry:每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。

导入jar包

<dependency>
    <groudId>javax.cache<groudId>
    <artifactId>cache-api<artifactId>
<dependency>

1.2 spring缓存抽象

在这里插入图片描述

Spring从3.1开始定义了org.springframework.cache.Cache

和org.springframework.cache.CacheManager接口来统一不同的缓存技术

并支持==JCache(JSR-107)==注解简化开发

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-cache</artifactId>
	</dependency>
  • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合
  • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache、EhCacheCache、ConcurrentMapCache等

使用Spring缓存抽象时我们需要关注以下两点

  • 确定方法需要被缓存以及他们的缓存策略
  • 从缓存中读取之前缓存存储的数据

重要概念&缓存注解

注:标注黄色为spring的注解

Cache缓存接口,定义缓存操作。实现有:RedisCache、EhCache、ConcurrentMapCache等
CacheManager缓存管理器,管理各种缓存(Cache)等
@Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict清空缓存
@CachePut保证方法被调用,又希望结果被缓存
@EnableCaching开启基于注解的缓存
keyGenerator缓存数据时key生成策略
serialize缓存数据时value序列化策略

1.3 @Cacheable体验

  1. 开启基于注解的缓存:@EnableCaching
  2. 标注缓存注解即可:
    1. @Cacheable
    2. @CacheEvict
    3. @CachePut

1.3.1 Cache SpEL available metadata(了解)

名字位置描述示例
methodNameroot Object当前被调用的方法名#root.methodName
methodroot object当前被调用的方法#root.method.name
targetroot object当前调用的目标对象#root.target
targetClassroot object当前调用的目标对象类#root.targetClass
argsroot object当前调用的方法的参数列表#root.args[0]
cachesroot object当前方法调用使用的缓存列表(如:Cacheable(value={“cache1”,“cache2”})),则有两个cache#root.caches[0].name
argument nameevaluation context方法的参数名,可以直接#参数名,也可以使用#p0或#a0的形式,0代表参数的索引#iban,#a0,#p0
resultevaluation context方法执行后的返回值(仅当方法执行之后的判断有效,如"unless",“cache put”)#result

1.4 缓存的工作原理&@CacheManager运行流程

原理:

  1. 自动配置类:CacheAutoConfiguration
  2. 缓存配置类
    1. GenericCacheConfiguration
    2. JCacheCacheConfiguration
    3. EhCacheCacheConfiguration
    4. HazelastCacheConfiguration
    5. InfinispanCacheConfiguration
    6. CaffeineCacheConfiguration
    7. CaffeineCacheConfiguration
    8. GuavaCacheConfiguration
    9. SimpleCacheConfiguration
    10. NoOpCacheConfiguration
  3. 哪个配置类默认生效?SimpleCacheConfiguration
  4. 给容器注册了一个CacheManager:ConcurrentMapCacheManager
    1. 可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中

运行流程:@Cacheable

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

在这里插入图片描述

/**
 * 将方法运行的结果缓存,以后再要相同的数据,直接从缓存里面获取,不用调用方法
 *
 * CacheManager管理多个Cache组件的,对缓存真正的CRUD操作在cache组件中,每一个缓存的组件都有自己唯一的名字
 *
 * 几个属性:
 *      cacheNames/value:指定缓存的组件名字
 *      key:缓存数据使用的key;默认使用方法参数的值  例如:id传入1 key:1 value:方法返回值; 
 *		1:方法返回值。key可以编写Spel表达式
 *
 *      keyGenerator:key的生成器;可以自己指定key的生成器的组件id
 *                   key和keyGenerator二选一
 *      cacheManager:指定缓存管理器;或者cacheResolver 二选一
 *      condition:指定符合条件情况下才缓存
 *      unless:否定缓存;当unless指定的条件为true,方法的返回值不会被缓存;可以获取到结果进行判断
 *              unless = "#result==null"
 *      sync:是否使用异步操作
 *
 * @param id
 * @return
*/
@Cacheable(cacheNames={"emp"})
public Map<String, Object> getUser(){
    return jdbcTemplate.queryForMap("select * from demo");
}

1.5 @CachePut

既调用方法,又更新缓存数据

修改了数据库的某个值,同时更新缓存

先掉方法,将目标方法的结果缓存起来

如果返回的是null,则会清除缓存,相当于CacheEvict操作
如果不是null,则修改完之后,会将缓存返回值,做一次更新操作

@Cache(value="emp",key="#result.id")
public User updateUser(User user){
    mapper.updateUser(user);
    return user;
}

**注意:**存缓存的key和更新缓存的key要一致才能达到效果

1.6 CacheEvict

缓存清除,数据库删除数据,之前缓存的数据也删除掉

key值也要一致

allEntries:清除所有的数据 true

@CacheEvict
public void deleteUser(Integer id){
    mapper.delete(id);
}

1.7 @Caching&CacheConfig

@Caching:这是一个组合注解。包含了@Cacheable、@Cacheput、CacheEvict

@Caching(
	cacheable={
        @Cacheable(value="emp",key="#lastName")
    },
    put={
        @CachePut(value="emp",key="#result.id")
    }
)
public User getUserByLastName(String lastName){
    return userMapper.getUserLastName(lastName);
}

@CacheConfig:标注在类上的,value值就是缓存的名:抽取缓存的公共配置

二、搭建redis环境

前言

springboot2.x之后。原来使用的jedis被替换成了lettuce

jedis:采用的直连,多个线程操作的话不安全,如果先要避免,需要使用jedis pool连接池。像BIO模式

lettuce:采用netty,实例可以再多个线程中进行共享,不存在线程安全问题,减少线程数据了,像NIO模式

2.1 RedisTemplate&序列化机制

导入maven依赖
<dependency>
   org.springframework.boot
   spring-boot-starter-data-redis
<dependency>    

配置文件指定redis的ip端口

spring.redis.host=指定的ip

2.2 RedisAutoConfiguration

两大核心模板组件

@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object,Object> redisTemplate(){
    
}

@Bean
@ConditionalOnMissingBean(name = StringRedisTemplate.class)
public StringRedisTemplate<Object,Object> stringRedisTemplate(){
    
}


//操作k-v字符串
@Autowired
StringRedisTemplate stringRedisTemplate;
    
//k-v都是对象
@Autowired
RedisTemplate redisTemplate;

2.3 Redis常见的五大类型操作

  1. String
  2. List
  3. Set
  4. Hash
  5. ZSet
  • stringRedisTemplate.optForValue():操作字符串
  • stringRedisTemplate.optForList():操作列表
  • stringRedisTemplate.optForSet():操作集合
  • stringRedisTemplate.optForHash():操作散列
  • stringRedisTemplate.optForZSet():操作有序结合

2.4 如何改变默认的序列化机制

默认保存对象,使用的是JDK序列化机制

redisTemplate.opsForValue().set("emp",User)

想以JSON方式来保存

  1. 自己将对象转换为JSON
  2. 自定义序列化机制
@Configuration
public class MyCacheConfig{
    
@Bean
public RedisTemplate<Object,User>redisTemplate(RedisConnectionFactory Factory)
	{
    RedisTemplate<Object,User> redis = new RedisTemplate();
    
    redis.setConnectionFactory(Factory);
    
    Jsckson2JsonRedisSerializer j = new Jsckson2JsonRedisSerializer<User>(User.class);
    
    redis.setDefaultSerializer(j);
    		
        	
    }
}

2.5 自定义CacheManager

原理:CacheManager === cache 缓存组件来实际给缓存中存储数据

  1. 引入redis的starter,容器中保存的是RedisCacheManager

  2. RedisCacheManager帮我们创建RedisCache 来作为缓存组件 RedisCache通过操作redis缓存数据

  3. 默认保存数据 k-v 都是Object,都是序列化;如何保存json

    1. 引入redis的starter,cacheManager变为RedisCacheManager
    2. 默认床架你的redisCacheManager 操作redis 使用的是RedisTemplate<Object,Object>
    3. RedisTemplate<Object,Object> 默认使用JDK序列化机制
  4. 自定义cacheManager

    @Configuration
    public class MyRedisConfig{
        
        @Bean
        public RedisTemplate<Object,Employee> emRedisTemplate(
        	RedisConnectionFactory redisConnectionFactroy)
        {
            RedisTemplate<Object,Employee> redis = new RedisTemplate();
            
            redis.setConnectionFactory(redisConnectionFactroy);
            
            Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer(Employee.class);
            template.setDefaultSerializer(ser);
            return template;
        }
        
        
        @Bean
        public RedisCacheManager employeeCacheManager(RedisTemplate<Object,Employee> emRedisTemplate){
            RedisCacheManager cache = new RedisCacheManager(emRedisTemplate);
            cache.setUsePrefix(true);
            return cache;
        }
    }
    
    
  5. 操作流程

    public class DeptService{
        @Autowried
        DeptService service;
        
        //缓存的数据能存入redis
        //第二次读取缓存查询就不能反序列化回来,因为存的json数据是emp的;
        @Cacheable(cacheNames="dept")
        public Department getDeptById(Integer id){
            Department department = service.getDeptById(id);
            return department;
        }
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值