博客
关于我
SpringBoot缓存入门篇
阅读量:338 次
发布时间:2019-03-04

本文共 6188 字,大约阅读时间需要 20 分钟。

首先我来简单的说一下为什么要使用缓存:使用缓存的最大好处就是他能减少服务端频繁的访问数据库,比如将第一次从数据库查询的商品信息放入缓存中,之后如果有很多用户查看商品信息的话,他就直接从缓存中查询,验证码这些生命周期短暂的信息也可放入缓存中处理。
创建SpringBoot项目的时候,勾选下面的几个模块:

在这里插入图片描述
正式使用前应在springboot主类上加上下面的注解:
在这里插入图片描述
省略数据库表的创建,以及配置信息,和mapper文件(有问题的话可以看)…毕竟本文主要讲缓存嘛。
项目是借助注解来使用缓存的,一般而言注解一般用于Service层!
在这里插入图片描述
主要参数如下:
在这里插入图片描述

直接举例子:

1.@Cacheable

下面是Service层的一条根据id查询员工的方法,加上@Cacheable注解之后,第二次在调用该方法就会直接在缓存中查询。

/**     * 将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法;     * CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;     *     *     * 原理:     *   1、自动配置类;CacheAutoConfiguration     *   2、缓存的配置类     *   org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】     *   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration     *   3、哪个配置类默认生效:SimpleCacheConfiguration;     *     *   4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager     *   5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;     *     *   运行流程:     *   @Cacheable:     *   1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;     *      (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。     *   2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;     *      key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;     *          SimpleKeyGenerator生成key的默认策略;     *                  如果没有参数;key=new SimpleKey();     *                  如果有一个参数:key=参数的值     *                  如果有多个参数:key=new SimpleKey(params);     *   3、没有查到缓存就调用目标方法;     *   4、将目标方法返回的结果,放进缓存中     *     *   @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,     *   如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;     *     *   核心:     *      1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件     *      2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator     *     *     *   几个属性:     *      cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;     *     *      key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值  1-方法的返回值     *              编写SpEL; #i d;参数id的值   #a0  #p0  #root.args[0]     *              getEmp[2]: root.methodName+"["+#id+"]"     *     *      keyGenerator:key的生成器;可以自己指定key的生成器的组件id     *              key/keyGenerator:二选一使用;     *     *     *      cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器     *     *      condition:指定符合条件的情况下才缓存;     *              ,condition = "#id>0"     *          condition = "#a0>1":第一个参数的值》1的时候才进行缓存     *     *      unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断     *              unless = "#result == null"     *              unless = "#a0==2":如果第一个参数的值是2,结果不缓存;     *      sync:是否使用异步模式     * @param id     * @return     *     */	@Cacheable(value = {   "emp"})    public Employee getEmp(Integer id){           System.out.println("查询"+id+"号员工");        Employee emp = employeeMapper.getEmpById(id);        return emp;    }

key默认就是id,而value和cacheNames是一个意思,所以上面的注解等价于@Cacheable(cacheNames = “emp”,key="#id")
如果想换成自己的key,比如想要换成 getEmp[2]
则key="#root.methodName+’[’+#id+’]’ "
也可以用keyGenerator来指定key值:
先给容器注入下面的bean:

 @Bean("myKeyGenerator")    public KeyGenerator keyGenerator(){           return new KeyGenerator(){               @Override            public Object generate(Object target, Method method, Object... params) {                   return method.getName()+"["+ Arrays.asList(params).toString()+"]";            }        };    }

用的时候:

@Cacheable(value = {"emp"},keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#a0==2")

2.@CachePut
加上该注解,我觉得有最值得注意的意义是:1.加上该注解的方法,一定会被执行(什么意思?意思就是如果方法是查询方法,即便结果是在缓存中,只要方法里面有调用数据库的查询,他依旧访问数据库)2.一定要确定好他的key(比如我查询了1号学生的信息,并且放在了key为stu1的缓存中,你现在想在修改学生数据库信息的同时,也修改缓存中的信息,就得加上该注解,且key值也必须是stu1,不能是其他的!)

 /**     * @CachePut:既调用方法,又更新缓存数据;同步更新缓存     * 修改了数据库的某个数据,同时更新缓存;     * 运行时机:     *  1、先调用目标方法     *  2、将目标方法的结果缓存起来     *     * 测试步骤:     *  1、查询1号员工;查到的结果会放在缓存中;     *          key:1  value:lastName:张三     *  2、以后查询还是之前的结果     *  3、更新1号员工;【lastName:zhangsan;gender:0】     *          将方法的返回值也放进缓存了;     *          key:传入的employee对象  值:返回的employee对象;     *  4、查询1号员工?     *      应该是更新后的员工;     *          key = "#employee.id":使用传入的参数的员工id;     *          key = "#result.id":使用返回后的id     *             @Cacheable的key是不能用#result     *      为什么是没更新前的?【1号员工没有在缓存中更新】     *     */    @CachePut(/*value = "emp",*/key = "#result.id")    public Employee updateEmp(Employee employee){           System.out.println("updateEmp:"+employee);        employeeMapper.updateEmp(employee);        return employee;    }

3.@CacheEvict
这里我就说一下 beforeInvocation属性吧,默认为false,意思是在执行在该方法之后,清除key所对应的缓存如果遇到异常就清除不了了,如果属性值为true则在方法调用前执行清除操作。

    /**     * @CacheEvict:缓存清除     *  key:指定要清除的数据     *  allEntries = true:指定清除这个缓存中所有的数据     *  beforeInvocation = false:缓存的清除是否在方法之前执行     *      默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除     *     *  beforeInvocation = true:     *      代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除     *     *     */    @CacheEvict(value="emp",beforeInvocation = true/*key = "#id",*/)    public void deleteEmp(Integer id){           System.out.println("deleteEmp:"+id);        //employeeMapper.deleteEmpById(id);        int i = 10/0;    }

4.Caching
这是个复合注解,可以涵盖上面的注解:

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

另外补充一个注解:
可以在Service类的前面加上@CacheConfig:抽取缓存的公共配置,下面的缓存注解就可以不写value了,value值统一为emp!

在这里插入图片描述

转载地址:http://hbhe.baihongyu.com/

你可能感兴趣的文章
CSUST 2021 周赛 2 题解
查看>>
【人脸识别】基于matlab GUI灰度化教室人数统计【含Matlab源码 602期】
查看>>
前后端数据交互之表单
查看>>
剑指offer JZ15 反转链表
查看>>
剑指offer JZ21 栈的压入弹出序列
查看>>
剑指offer JZ31 整数中1出现的次数
查看>>
实现基于scrapy框架的天气预报爬虫hengYangSpaider @572311文
查看>>
maven打包指定名称并去除jar-with-dependencies后缀
查看>>
Netty4服务端入门代码示例
查看>>
java连接mysql,jdbc驱动
查看>>
python 垃圾回收机制 以及 内存管理
查看>>
C++中的static成员函数以及static成员变量详解
查看>>
操作系统前传第六课--开发中的辅助工具
查看>>
Linux系统编程44 信号 - 信号的响应过程分析!!!
查看>>
QT17 - 对话框及其类型 QDialog
查看>>
设备驱动之阻塞
查看>>
Binder进程间通信系统第三篇-----Binder进程间通信之 MediaServer 简析
查看>>
电平触发设备休眠唤醒--输入子系统+内核线程
查看>>
python数据类型
查看>>
机器学习之九:提升树和GBDT
查看>>