范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

6000字统一缓存帝国实战SpringCache

  本篇我来向大家介绍一种兼容所有缓存中间件的方案,不论我们是使用 Redis 还是 Ehcache,都不需要关心如何操作 Redis 或者 Ehcache,这套方案统统帮你搞定。
  这套方案就是大名鼎鼎的  Spring Cache  。什么?你没有听过,没关系,本篇带你一起探索。
  缓存系列文章:
  《缓存实战(一)》
  《缓存实战(二)Redis分布式锁》
  《缓存实战(三)Redisson 分布式锁》 一、揭开 Spring Cache 的面纱1.1 现有缓存方案的痛点
  试想一种场景 :
  1.用户 A 打开 APP,进入到了秒杀商品的详情页,那这个商品数据我们会先去数据库查询,然后返回给客户端。
  2.因为有大量用户短时间内进入到了详情页,所以可以把活动列表缓存起来,直接读缓存就可以了。
  3.那下次再查询商品时,直接去缓存查询就可以了。如果秒杀商品下架了,缓存的数据不会用到了,就把缓存删掉就可以了。
  4.上面几步看起来也没啥问题,但是放缓存,删除缓存这两步是需要我们去手动写代码实现的。有没有一种方式不用写操作缓存的代码?
  5.假如现在用的缓存中间件是 Redis,领导说要换成 Ehcache,操作缓存的代码是不是又得重新撸一遍?
  总结下上面场景的痛点: 需要手写操作缓存代码,如添加缓存、更新缓存、删除缓存。 切换缓存组件并不容易,或者说没有对缓存层进行抽象封装,依赖具体的缓存中间件。
  哪有没有一种方案可以帮助解决上面的两个痛点呢?
  这就是今天要介绍的  Spring Cache  。1.2 Spring Cache 介绍
  Spring Cache 是 Spring 提供的一整套的缓存解决方案。虽然它本身并没有提供缓存的实现,但是它提供了一整套的接口和代码规范、配置、注解等,这样它就可以整合各种缓存方案了,比如 Redis、Ehcache,我们也就不用关心操作缓存的细节。
  Spring 3.1 开始定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术,并支持使用注解来简化我们开发。
  Cache   接口它包含了缓存的各种操作方式,同时还提供了各种xxxCache  缓存的实现,比如 RedisCache 针对Redis,EhCacheCache 针对 EhCache,ConcurrentMapCache 针对 ConCurrentMap,具体有哪几种,后面实战中会介绍。1.3 Spring Cache 有什么功效
  每次调用某方法,而此方法又是带有缓存功能时,Spring 框架就会检查 指定参数  的那个方法是否已经被调用过,如果之前调用过,就从缓存中取之前调用的结果;如果没有调用过,则再调用一次这个方法,并缓存结果,然后再返回结果,那下次调用这个方法时,就可以直接从缓存中获取结果了。1.4 Spring Cache 的原理是什么?
  Spring Cache 主要是作用在类上或者方法上,对类中的方法的返回结果进行缓存。那么如何对方法增强,来实现缓存的功能?
  学过 Spring 的同学,肯定能一下子就反应过来,就是用  AOP  (面向切面编程)。
  面向切面编程可以简单地理解为在类上或者方法前加一些说明,就是我们常说的注解。
  Spring Cache 的注解会帮忙在方法上创建一个切面(aspect),并触发缓存注解的切点(poinitcut),听起来太绕了,简单点说就是:Spring Cache 的注解会帮忙在调用方法之后,去缓存 方法调用的最终结果 ,或者在方法调用之前拿缓存中的结果,或者删除缓存中的结果,这些读、写、删缓存的脏活 都交给 Spring Cache 来做了,是不是很爽,再也不用自己去写缓存操作的逻辑了。1.5 缓存注解
  Spring 提供了四个注解来声明缓存规则。@Cacheable,@CachePut,@CacheEvict,@Caching。
  大家先有个概念,后面我们再来看怎么使用这些缓存注解。 二、使用缓存2.1 引入 Spring Cache 依赖
  在 pom 文件中引入 spring cache 依赖,如下所示:      org.springframework.boot     spring-boot-starter-cache  2.2 配置使用哪种缓存
  Spring Cache 支持很多缓存中间件作为框架中的缓存,总共有 9 种选择: caffeine:Caffeine 是一种高性能的缓存库,基于 Google Guava。 couchbase: CouchBase 是一款非关系型JSON文档数据库。generic:由泛型机制和 static 组合实现的泛型缓存机制。 hazelcast:一个高度可扩展的数据分发和集群平台,可用于实现分布式数据存储、数据缓存。 infinispan:分布式的集群缓存系统。 jcache:JCache 作为缓存。它是 JSR107 规范中提到的缓存规范。 none:没有缓存。 redis:用 Redis 作为缓存 simple:用内存作为缓存。
  mark
  我们还是用最熟悉的 Redis 作为缓存吧。配置 Redis 作为缓存也很简单,在配置文件 application.properties 中设置缓存的类型为 Redis 就可以了, 如下所示:
  当然,别忘了还要在 pom 文件中 引入 Redis 的依赖,不然用不了 Redis。      org.springframework.boot     spring-boot-starter-data-redis  2.3 测试缓存
  那基础的配置已经做好了,现在就是看怎么使用 Spring Cache 了。
  (1)启动类上添加  @EnableCaching  注解。本文案例就是在 启动类 PassjavaQuestionApplication 添加 @EnableCaching注解。
  (2)指定某方法开启缓存功能。在方法上添加  @Cacheable   缓存注解就可以了。
  @Cacheable 注解中,可以添加四种参数:value,key,condition,unless。首先我们来看下 value 参数。
  下面的代码出于演示作用,用了最简单的逻辑,test 方法直接返回一个数字,连数据库查询都没有做。不过没关系,我们主要验证 Spring Cache 是否对方法的结果进行了缓存。 @RequestMapping("/test") @Cacheable({"hot"}) public int test() {     return 222; }
  大家注意,@Cacheable 注解中小括号里面还含有大括号,大括号里面还有 "hot" 字符串,这个 hot 字符串你可以把它当作一个缓存的名字,然后将 test 方法返回的结果存到 hot 缓存中。我们也可以用 value="hot" 的方式。
  第一次调用 test 方法前,既没有 hot 缓存,更没有 test 的结果缓存。
  调用 test 方法后,Redis 中就创建出了 hot 缓存了,然后缓存了一个 key,如下图所示:
  第二次调用 test 方法时,就从缓存 hot 中将 test 方法缓存的结果 222 取出来了,为了验证没有执行 test 中的方法,大家可以在 test 方法中打下 log 或者断点。最后的验证结果肯定是没有走 test 方法的,而是直接从缓存中获取的。
  那我们再来测试一个方法,方法名改为 test2,且请求路径也改为 test2 了。 @RequestMapping("/test2") @Cacheable({"hot"}) public int test2() {     return 456; }
  大家觉得这两个方法的结果都会缓存吗?还是只会缓存第一个被调用的方法?
  经过测试,执行第一个 test 方法后,再执行 test2 方法,缓存结果一直是 222 不会变。因为他们的 key 都是 默认的 SimpleKey[],所以两个方法对应的缓存的 key 都叫这个,所以得到的缓存值是一样的。
  (3)加上数据库查询的测试。
  有的同学可能觉得上面的测试太简单了,test 方法里面啥都没做,还缓存啥呢,完全没必要啊。没关系,大家的顾虑是对的,我们来加上数据库查询,安排~
  先说下场景:前端需要查询某个题目的详情,正常逻辑是查询数据库后返回结果。假定这个查询操作非常频繁,我们需要将题目详情进行缓存。我们先看看常规 Redis 缓存方案:
  先从 Redis 缓存中查看缓存中是否有该题目,如果缓存中有,则返回缓存中的题目;如果没有,就从数据库中查。查询出题目后,就用 Redis 存起来,然后返回。这里就要写操作 Redis 的代码了:查询 Redis 缓存、更新 Redis 缓存。 // 查询缓存,假定该题目详情缓存的 key=question1 redisTemplate.opsForValue().get("question1");  // 更新缓存 redisTemplate.opsForValue().set("question1", questionEntity);
  那如果用 Spring Cache 注解的话,上面两行代码可以直接干掉了。如下所示,加一个 @Cacheable 注解搞定。 @Cacheable({"question", "hot"}) public QuestionEntity info(Long id) {     return getById(id); // 查询数据库操作 }
  其中 question 和 hot 是缓存的名字,我们可以将结果放到不同的缓存中。
  结论: 如果没有指定请求参数,则缓存生成的 key name,是默认自动生成的,叫做 SimpleKey[]。 如果指定了请求参数,则缓存的 key name 就是请求参数,比如上面 info 方法,key 等于我传入的 id = 1。 缓存中 key 对应的 value 默认使用 JDK 序列化后的数据。 value 的过期时间为 -1,表示永不过期。 2.4 自定义配置类
  上面保存的缓存数据都是默认设置,我们也可以自己定义配置,如下所示,在配置文件 application.properties 添加如下配置: # 使用 Redis 作为缓存组件 spring.cache.type=redis # 缓存过期时间为 3600s spring.cache.redis.time-to-live=3600000 # 缓存的键的名字前缀 spring.cache.redis.key-prefix=passjava_ # 是否使用缓存前缀 spring.cache.redis.use-key-prefix=true # 是否缓存控制,防止缓存穿透 spring.cache.redis.cache-null-values=true
  然后需要加一个配置类:MyCacheConfig。可以在我的开源项目 passjava 获取完整源码。 RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) { } 2.5 自定义 key
  然后我们可以指定 key 的值,可以在 @Cacheable 注解里面加上 key 的值  #root.method.name  。这是一种特有的表达式,称作 SpEL   表达式,这里代表用方法名作为缓存 key 的名字。@Cacheable(value = {"hot"}, key = "#root.method.name")
  接下来就是见证奇迹的时刻,调用 test 方法和 test2 方法,发现有两个不同的 key,一个是 passjava_test1,另外一个 passjava_test2,它们的 key 就是前缀 passjava_ + 方法名 组成。
  SpEL 表达式还有很多其它规则,如下所示:
  可以根据项目需要选择合适的表达式来自定义 key。 2.6 自定义条件
  除了设置缓存条目的 key,我们还可以自定义条件来决定是否将缓存功能关闭。这里就要用到@Cacheable 另外两个属性:condition 和 unless,它俩的格式还是用 SpEL 表达式。对应的四个属性总结如下:
  代码示例如下: @Cacheable(value = "hot", unless = "#result.message.containss("NoCache")")
  当放回的结果 message 字段包含有 NoCache 就不会进行缓存。 2.7 更新注解
  @CachePut  也是用来更新缓存,和 @Cacheable 非常相似,不同点是 @CachePut 注解的方法始终都会执行,返回值也会也会放到缓存中。通常用在保存的方法上。
  保存成功后,可以将 key 设置保存实例的 id。这个怎么做呢?
  之前我们说过 key 可以通过 SpEL 表达式来指定,这里就可以搭配 #result.id 来实现。
  这里还是用个例子来说明用法:创建题目的方法,返回题目实例,其中包含有题目 id。 @RequestMapping("/create") @CachePut(value = "hot", key = "#result.id") public QuestionEntity create(@Valid @RequestBody QuestionEntity question){     return IQuestionService.createQuestion(question); }
  保存的 id 是自增的,值为 123,所以缓存中的 key = passjava_123。
  2.8 删除缓存注解
  @CacheEvict  注解的方法在调用时不会在缓存中添加任何东西,但是会从从缓存中移除之前的缓存结果。
  示例代码如下: @RequestMapping("/remove/{id}") @CacheEvict(value = "hot") public R remove(@PathVariable("id") Long id){     IQuestionService.removeById(id);     return R.ok(); }
  删除条目的 key 与传递进来的 id 相同。我测试的时候传的 id = 123,经过前缀passjava_组装后就是 passjava_123,所以将之前缓存的 passjava_123 删除了。重复执行也不会报错。
  注意:@CacheEvict 和 @Cacheable、@CachePut 不同,它能够应用在返回值为 void 的方法上。
  @CacheEvict 还有些属性可供使用,总结如下:
  三、 总结
  本文通过传统使用缓存的方式的痛点引出 Spring 框架中的 Cache 组件。然后详细介绍了 Spring Cache 组件的用法: 五大注解。@Cacheable、@CachePut、@CacheEvict、@Caching,、@CacheConfig。 如何自定义缓存条目的 key。 如何自定义 Cache 配置。 如何自定义缓存的条件。
  当然 Spring Cache 并不是万能的,缓存一致性问题依旧存在,下一篇,我们再细聊缓存的一致性问题。
  原文链接:https://mp.weixin.qq.com/s/OgwyHwJqGUncqOVJoP4qwg

DNF为竞速而生的职业,前50名占据15席,内卷太严重了DNF为竞速而生的职业,前50名占据15席,内卷太严重了由旭旭宝宝主办的第四届国服巅峰竞速争霸赛,预赛阶段的结果出炉,前50支大神队伍全部亮相,八仙过海各显神通,通关速度一个比一个科幻作家的星际战争假想依据之前有读者质疑我们在太空真空无重力的环境下,以亚光速度高速在太空中飞行的两方人马的太空战舰是怎么停下来的?太空之城里的片段其实这个问题太小儿科了,对与已经可以在太空发动战争的人类文2022年LPL春季赛1月10日开赛,最具上限三大队伍盘点2022年LPL春季赛已经确认于1月10日开赛,今年的LPL竞争必然十分激烈,因为冬季转会期各大战队人员变动极大,不仅缔造了全华班强强相争格局,不少队伍还更换的建队基石,在春季赛开能让用户不卸载也是本事,送金币送福利买断版权,你觉得呢?用习惯了,也就不会卸载了。1。不同的阶段,我最喜欢的APP不同2017年8月份,我注册QQ,开启了我的互联网创作之路。2021年走向尾声,从QQ已经变成了抖音。现在我最喜欢的软件应明知道超越不了王者,英雄联盟为什么要坚持推出手游?明明知道超越不了王者荣耀,为什么还要推出英雄联盟手游呢?原因确是让人意想不到,当英雄联盟手游还没推出来的时候,很多人都说,只要一上线,王者荣耀就会彻底凉凉。现实情况却是非常打脸,王排面!狼队Fly上央视频,凡尔赛发言让粉丝忍俊不禁伴随着2022年的到来,近日,由央视频创新推出的30小时不间断伴随式跨年直播节目闪耀吧2022吸引了不少电竞爱好者们的关注。因为在闪耀吧2022中,就邀请到了英雄联盟LPL职业联赛大家2022新年快乐传世一直在这里等你哈喽呀,我的朋友们好呀。我是大林,今天先祝大家2022年,新年快乐。今天想给大家介绍一款手游传世群英,这款游戏是三职业微变版本,也是一款经典传奇类的冒险类游戏,玩过游戏的好多玩家都王者荣耀挑战者杯羲和张飞关键开团吼中三人,XYG战胜东莞Wz2021年王者荣耀挑战者杯选拔赛第二个比赛日第四场比赛由XYG对阵东莞Wz,赛制为BO1。最终,XYG战胜东莞Wz,XYG取得两连胜。2分钟,XYG上路四包二越塔失败,云游夏侯惇一漫威对决烂分恰到饱希娜振奋流作者NGA白熊代言人因为喜欢瑟西把敌人变成花瓣特效而组的一套卡组,经测试实战效果还不错,分享给大家。卡组构成卡组梯队T1。5成型站位1。莱格巴(希娜之剑)2。阿贾克(希娜之剑)3。新赛季如何克制点燃法?美服传说第二的针对构筑推荐2022年已经到来了,在这里祝贺大家新年快乐!奥特兰克的最新平衡补丁,主要是针对标准模式,对狂野模式的影响还是比较小,海盗战和冰萨还是非常强势。当然,提到狂野模式中最强的卡组,那肯英雄联盟格斗游戏即将来袭游戏联盟衍生动画剧集双城之战第一季迎来了大结局。故事也在一个高潮的地方被掐断了,这很明显是会出第二季动画。同时以英雄联盟宇宙为背景的2v2组队格斗游戏projectL研发进度也进行
阴阳师碎片交换功能已上线,却依旧有人被骗?老玩家说出真相如果你经常逛论坛的话你可能会以为阴阳师里面每个人都是全图鉴或者是每个人都能一发入魂直接抽中几个SSR,但是真实的现状却是拥有好的式神只有几个人,而每次新式神来临的时候几十抽就能抽中云顶之弈S5。5赛季重磅更新,光明取代黑暗,触发残血新机制终于玩家们看见了希望,终于玩家们即将脱离掉这个无聊到让人发慌的赛季了,因为在S5这个赛季的确让玩家们感觉到了这个游戏显得很无聊,而导致这个游戏无聊的原因来自于这个赛季给玩家们一种感阴阳师夏日游园会解析,百鬼夜戏有惊喜,联动萌宠免费拿这周阴阳师又出了新的活动,而这次活动让玩家们感觉到十分的振奋并且深受玩家们的好评,尤其是这次的活动风头直接盖过了新皮肤的出现,因为之前酒吞童子的皮肤在曝光的时候出现了一些负面影响,云顶之弈S5。5赛季7月份上线,花灯回归,玩家黑暗装备快删终于玩家们要远离这个让我们悲痛欲绝的S5赛季迎来了S5。5赛季,不过每次半赛季更新的时候有点像开盲盒一样,因为谁都不知道这个半赛季更新会如此,说不定会比原来的赛季更差更无聊。不过很云顶之弈运营已无效,吃鸡靠运气,玩家王者都是欧皇?云顶之弈S5赛季是玩家们意见最多的一个赛季也是遭遇到了玩家们无情地吐槽,因为这个赛季的问题很多,其中遭遇到玩家们吐槽最多的一点在于不少人说这个赛季根本不需要运营,如果你运气够好就能剑网三缘起为什么怀旧服受玩家欢迎?装饰换时间,玩家还有谁一开始想象不到为什么一款游戏会如此热门,因为开剑网三怀旧服开始的时候我也去抢了激活码,那个时候抢到了,我的第一印象就是这款游戏可能没有多少人关注才会如此简单。但是当我随手将剑网三怀云顶之弈玩家吐槽,游戏只为上分,一个阵容躺赛季?快乐的游戏还是安安静静地上分,当这两个选项摆在你面前的时候你将如何选择?如果是在英雄联盟游戏中,我相信每一个玩家都会选择上分而不是快乐的游戏,因为你一旦选择了快乐游戏你会发现你的四云顶之弈5。5版本巨变,光明哨兵加入游戏,黑暗装备惨遭移除云顶之弈的新版本即将更新,玩家们对于S5。5赛季寄予厚望,或者说被当作S5赛季的转载点,因为在之前的版本过于无聊让玩家们开始逐渐去厌烦掉云顶之弈游戏,不过S5。5赛季的话相对来说会阴阳师为了活动不择手段,阴阳寮再现阴间公告,劝退寮友这次阴阳师的活动可谓是几家欢乐几家愁,活动开启的时候很多人评价说这次的青森之秘活动其实是为了拯救老区的一些僵尸寮,能让他们在活动中快速的崛起,从而解决掉因为寮成员不足而导致的寮资金阴阳师重磅更新,无限利好老区玩家,道馆难度降低阴阳师一直在给老区的阴阳寮降低难度,如果老区的阴阳寮生存难度不降低的话,那么在老区中基本上就难以生存下来了,新区的阴阳寮每天固定十个寮包并且大家一直都会在做寮30,但是老区会出现一阴阳师120万叶子难以集齐,无缘SP式神?这个技巧不能忘记自从青森之秘这个活动开启以来,每次进入阴阳师或者是阴阳寮的群里总觉得自己倍感压力,因为每次都会有会长或者是一些管理人员跟你说快点去刷这个活动,但是因为自己一直时间不多所以比较佛系,