您的位置:首页 > 编程语言 > Java开发

SpringBoot系列之缓存使用教程

2020-04-03 21:42 465 查看
介绍SpringBoot项目中使用缓存,之前先介绍一下Spring的缓存抽象和JSR107,本博客是我在学习尚硅谷视频和参考其它博客之后做的笔记,仅供学习参考 @[toc] ## 一、Spring的缓存抽象 ### 1.1、缓存抽象定义 Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用Java Caching(JSR-107)注解简化我们进行缓存开发。Spring Cache 只负责维护抽象层,具体的实现由你的技术选型来决定。将缓存处理和缓存技术解除耦合。 ### 1.2、重要接口 * Cache:缓存抽象的规范接口,缓存实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 * CacheManager:缓存管理器,管理Cache的生命周期 ## 二、JSR107 ### 2.1、JSR107核心接口 Java Caching(JSR-107)定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry和 Expiry。 * CachingProvider:创建、配置、获取、管理和控制多个CacheManager * CacheManager:创建、配置、获取、管理和控制多个唯一命名的Cache,Cache存在于CacheManager的上下文中。一个CacheManager仅对应一个CachingProvider * Cache:是由CacheManager管理的,CacheManager管理Cache的生命周期,Cache存在于CacheManager的上下文中,是一个类似map的数据结构,并临时存储以key为索引的值。一个Cache仅被一个CacheManager所拥有 * Entry:是一个存储在Cache中的key-value对 * Expiry:每一个存储在Cache中的条目都有一个定义的有效期。一旦超过这个时间,条目就自动过期,过期后,条目将不可以访问、更新和删除操作。缓存有效期可以通过ExpiryPolicy设置 ### 2.2、JSR107图示 引用尚硅谷视频课件中的图示: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200331181533420.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ0MjczOTE=,size_16,color_FFFFFF,t_70) ## 三、Spring缓存使用 ### 3.1、重要注解简介 例子实践之前,先简单介绍Spring提供的重要缓存注解 * @Cacheable:针对方法配置,能够根据方法的请求参数对其结果进行缓存 * @CacheEvict:清空缓存 * @CachePut:既调用方法,又更新缓存数据 * @EnableCaching:开启基于注解的缓存 * @Caching:定义复杂的缓存规则 ### 3.2、环境准备 ok,本博客以尚硅谷视频例子进行改写,用这个比较经典的例子进行说明 环境准备: * maven环境 * IntelliJ IDEA 新建两张表: ```sql DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `lastName` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `gender` int(2) DEFAULT NULL, `d_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` ```sql DROP TABLE IF EXISTS `department`; CREATE TABLE `department` ( `id` int(11) NOT NULL AUTO_INCREMENT, `departmentName` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` ### 3.3、引入spring-boot-starter-cache模块 ```xml ``` ### 3.4、主要注解例子实践 #### 3.4.1、@EnableCaching @EnableCaching开启基于注解的缓存 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class SpringbootCacheApplication { public static void main(String[] args) { SpringApplication.run(SpringbootCacheApplication.class, args); } } ``` #### 3.4.2、@Cacheable注解 @Cacheable注解的作用,前面也简介了,主要是针对方法配置,能够根据方法的请求参数对其结果进行缓存,介绍一下注解的主要属性 * cacheNames/value:指定缓存组件的名字,数组形式 * key:缓存数据使用的key,确定缓存可以用唯一key进行指定;eg:编写SpEL; #id,参数id的值 ,,#a0(第一个参数), #p0(和a0的一样的意义) ,#root.args[0] * keyGenerator:key的生成器;可以自己指定key的生成器的组件id(注意: key/keyGenerator:二选一使用;不能同时使用) * cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器 * condition:指定符合条件的情况下才缓存;使用SpEl表达式,eg:condition = "#a0>1":第一个参数的值>1的时候才进行缓存 * unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;eg:unless = "#a0!=2":如果第一个参数的值不是2,结果不缓存; * sync:是否使用异步模式 ```java @Cacheable(value = {"emp"}, /*keyGenerator = "myKeyGenerator",*/key = "#id",condition = "#a0>=1",unless = "#a0!=2") public Employee getEmp(Integer id) { Employee employee = this.employeeMapper.getEmpById(id); LOG.info("查询{}号员工数据",id); return employee; } ``` 这里也可以使用自定义的keyGenerator,使用属性keyGenerator = "myKeyGenerator 定义一个@Bean类,将KeyGenerator添加到Spring容器 ```java @Configuration public class CacheConfig { @Bean(value = {"myKeyGenerator"}) public KeyGenerator keyGenerator(){ return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { return method.getName()+"["+ Arrays.asList(params).toString()+"]"; } }; } } ``` #### 3.4.3、@CachePut注解 @CachePut注解也是一个用来缓存的注解,不过缓存和@Cacheable有明显的区别是即调用方法,又更新缓存数据,也就是执行方法操作之后再来同步更新缓存,所以这个主键常用于更新操作,也可以用于查询,主键属性和@Cacheable有很多类似的,详情参看@link @CachePut源码 ```java /** * @CachePut:既调用方法,又更新缓存数据;同步更新缓存 * 修改了数据,同时更新缓存 */ @CachePut(value = {"emp"}, key = "#result.id") public Employee updateEmp(Employee employee){ employeeMapper.updateEmp(employee); LOG.info("更新{}号员工数据",employee.getId()); return employee; } ``` #### 3.4.4、 @CacheEvic注解 主要属性: * key:指定要清除的数据 * allEntries = true:指定清除这个缓存中所有的数据 * beforeInvocation = false:默认代表缓存清除操作是在方法执行之后执行 * beforeInvocation = true:代表清除缓存操作是在方法运行之前执行 ```java @CacheEvict(value = {"emp"}, beforeInvocation = true,key="#id") public void deleteEmp(Integer id){ employeeMapper.deleteEmpById(id); //int i = 10/0; } ``` #### 3.4.5、@Caching注解 @Caching 用于定义复杂的缓存规则,可以集成@Cacheable和 @CachePut ```java // @Caching 定义复杂的缓存规则 @Caching( cacheable = { @Cacheable(/*value={"emp"},*/key = "#lastName") }, put = { @CachePut(/*value={"emp"},*/key = "#result.id"), @CachePut(/*value={"emp"},*/key = "#result.email") } ) public Employee getEmpByLastName(String lastName){ return employeeMapper.getEmpByLastName(lastName); } ``` #### 3.4.6、 @CacheConfig注解 @CacheConfig注解可以用于抽取缓存的公共配置,然后在类加上就可以,eg:`@CacheConfig(cacheNames = {"emp"},cacheManager = "employeeCacheManager")` **附录拓展:SpEL表达式用法** Cache SpEL available metadata |名称 |位置 |描述 |示例 | |-------------|-------------------------|------------------------------------------------------------------|--------------------| |methodName |root对象 |当前被调用的方法名 |#root.methodname | |method |root对象 |当前被调用的方法 |#root.method.name | |target |root对象 |当前被调用的目标对象实例 |#root.target | |targetClass |root对象 |当前被调用的目标对象的类 |#root.targetClass | |args |root对象 |当前被调用的方法的参数列表 |#root.args[0] | |caches |root对象 |当前方法调用使用的缓存列表 |#root.caches[0].name| |argument Name|执行上下文(avaluation context)|当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数 |#artsian.id | |result |执行上下文(evaluation context)|方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false)|#result | ## 四、集成Redis缓存 ### 4.1、环境准备 基于前面的Spring缓存环境,集成redis要引入相关配置: ```bash ``` 切换缓存方式为Redis:`spring.cache.type=redis` ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200402173831209.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ0MjczOTE=,size_16,color_FFFFFF,t_70) ### 4.2、Redis配置类实现 RedisTemplate配置 ```java @Resource private LettuceConnectionFactory lettuceConnectionFactory; @Bean @Primary public RedisTemplate
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: