文章目录

  • redis缓存注解
    • 一.概念
    • 二.缓存编程
    • 三 设置缓存有效期
      • 1 配置文件
      • 2 Controller

redis缓存注解

Spring Boot缓存注解@Cacheable、@CacheEvict、@CachePut使用
@Cacheable(查询)
@CachePut(新增修改)
@CacheEvict(清空缓存)

一.概念

Spring Boot缓存注解@Cacheable、@CacheEvict、@CachePut使用

1、@Cacheable
可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。@Cacheable可以指定三个属性,value、key和condition。
参数 解释 example
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如: @Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”}
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @Cacheable(value=”testcache”,key=”#userName”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。
属性名称 描述 示例
methodName 当前方法名 #root.methodName
method 当前方法 #root.method.name
target 当前被调用的对象 #root.target
targetClass 当前被调用的对象的class #root.targetClass
args 当前方法参数组成的数组 #root.args[0]
caches 当前被调用的方法使用的Cache #root.caches[0].name
当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。

2、 @CachePut

 @CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

3、@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false。

beforeInvocation属性:清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

    /*** 清除缓存* allEntries = true:是否清除所有的缓存,默认值false* beforeInvocation:是否在方法执行之前清除缓存,默认在方法执行完成后清除缓存* @param id*/@CacheEvict(value = "user",key = "#id",allEntries = true,beforeInvocation = true)@RequestMapping("deleteCache")public void deleteCache(Integer id){System.out.println("-------deleteCache--------");}

二.缓存编程

1 配置文件application.yml

spring:redis:host: 116.62.68.112password: 123456port: 6379database: 1####swagger相关配置
swagger:base-package: com.chenyuntitle: redis-demodescription: redisversion: 1.1terms-of-service-url: www.bajin.comcontact:name: 80后互联网架构师-金霖海email: 2559226091@qq.com
2.在启动类上开启SpringBoot对缓存的支持@EnableCaching
3.在需要缓存的类或者方法上加缓存注解 @Cacheable方法的返回值会被以缓存的形式存储到redis中

相关代码

User类

package com.chenyun.pojo;import java.io.Serializable;public class User implements Serializable {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public User() {}public User(Integer id, String name) {this.id = id;this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}

CacheController

package com.chenyun.web;import com.chenyun.pojo.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RestController
public class CacheController {@Cacheable(value = "getUser")@PostMapping("getUser")public List<User> getUser(User user){System.out.println("--------------getUser");User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");ArrayList<User> arrayList = new ArrayList<>();arrayList.add(user1);arrayList.add(user2);arrayList.add(user3);return arrayList;}@Cacheable(value = "getUserById",key = "#user.id")@PostMapping("getUserById")public List<User> getUserById(@RequestBody User user){System.out.println("--------------getUserById");User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");ArrayList<User> arrayList = new ArrayList<>();arrayList.add(user1);arrayList.add(user2);arrayList.add(user3);return arrayList;}/*** 根据主键查询用户信息*/@Cacheable(value = "user",key = "#id")@PostMapping("getUserById/{id}")public User getUserById(@PathVariable("id") Integer id){System.out.println("------------getUserById");User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");if(id == 1){return user1;}else if(id == 2){return user2;}else if(id == 3) {return user3;}return null;}/*** 取多个参数作为组合键* @param idOne* @param idTwo* @return*/@Cacheable(value = "user",key = "#idOne+#idTwo")@PostMapping("getUserById2/{id1}/{id2}")public List<User> getUserById2(@PathVariable("id1") String idOne, @PathVariable("id2") String idTwo){System.out.println("--------------getUserById:"+idOne+"-"+idTwo);User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");ArrayList<User> arrayList = new ArrayList<>();arrayList.add(user1);arrayList.add(user2);arrayList.add(user3);return arrayList;}/*** 取多个参数作为组合键* @param idOne* @param idTwo* @return*/@Cacheable(value = "user",key = "{#idOne,#idTwo}",condition="#idOne=='2'")@PostMapping("getUserById3/{id1}/{id2}")public List<User> getUserById3(@PathVariable("id1") Integer idOne,@PathVariable("id2") Integer idTwo){System.out.println("--------------getUserById:"+idOne+"-"+idTwo);User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");ArrayList<User> arrayList = new ArrayList<>();arrayList.add(user1);arrayList.add(user2);arrayList.add(user3);return arrayList;}/*** 使用root作为组合键* @param idOne* @param idTwo* @return*/@Cacheable(value = "user_root",key = "#root.method")@PostMapping("getUserByIdRoot/{id1}/{id2}")public List<User> getUserByIdRoot(@PathVariable("id1") String idOne,@PathVariable("id2") String idTwo){System.out.println("--------------getUserById:"+idOne+"-"+idTwo);User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");ArrayList<User> arrayList = new ArrayList<>();arrayList.add(user1);arrayList.add(user2);arrayList.add(user3);return arrayList;}//新增-修改-------------------------------------------------------------------@CachePut(value = "user",key = "#user.id")@PostMapping("updateUser")public User updateUser(@RequestBody User user){System.out.println("-----------updateUser");return user;}@CachePut(value = "user",key = "#user.id")@PostMapping("add")public User add(User user){return user;}@CacheEvict(value = "user",key = "#id")@PostMapping("deleteCache/{id}")public void deleteCache(@PathVariable("id") Integer id){}
}

三 设置缓存有效期

1 配置文件

package com.chenyun.web;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;@Configuration
public class CacheConfig {@Autowiredprivate ApplicationContext applicationContext;@Autowiredprivate RedisConnectionFactory factory;@Bean@PrimaryRedisCacheManager redisCacheManager() {final RedisCacheWriter writer = RedisCacheWriter.nonLockingRedisCacheWriter(factory);final GenericJackson2JsonRedisSerializer jackson = new GenericJackson2JsonRedisSerializer();final RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jackson);final RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair).entryTtl(Duration.ofSeconds(30));final Map<String, RedisCacheConfiguration> conf = getConf();System.out.println(conf);return new RedisCacheManager(writer, config, conf);}@Beanpublic ConcurrentMapCacheManager cacheManager() {ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();return cacheManager;}private Map<String, RedisCacheConfiguration> getConf() {final Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Component.class);final List<CacheMap> collect = beansWithAnnotation.entrySet().stream().flatMap(entry -> {try {final Object value = entry.getValue();// 获得原本的class名字,spring代理的都是后面有$$直接截取即可String className = "";if (value.getClass().getName().contains("$")){className = value.getClass().getName().substring(0, value.getClass().getName().indexOf("$"));}else{className = value.getClass().getName();}// 获得原始的字节码文件,如果被spring 代理之后,方法上会获取不到注解信息final Method[] methods = Class.forName(className).getDeclaredMethods();return Arrays.stream(methods).flatMap(method -> {final Cacheable annotation = method.getAnnotation(Cacheable.class);if (annotation == null) {return null;}return Arrays.stream(annotation.cacheNames()).map(data -> {if (data.contains("#")) {// 包含自定义日期final String[] split = data.split("#");if (split.length != 2) {return null;}final CacheMap cacheMap = new CacheMap();cacheMap.setName(data);final String s = split[1];final int time = Integer.parseInt(s.substring(0, s.length() - 1));if (s.endsWith("s")) {cacheMap.setTtl(Duration.ofSeconds(time));} else if (s.endsWith("m")) {cacheMap.setTtl(Duration.ofMinutes(time));} else if (s.endsWith("d")) {cacheMap.setTtl(Duration.ofDays(time));}return cacheMap;}return null;}).filter(Objects::nonNull);});} catch (Exception e) {System.out.println("异常");return null;}}).collect(Collectors.toList());return collect.stream().collect(Collectors.toMap(CacheMap::getName, p -> {final GenericJackson2JsonRedisSerializer jackson = new GenericJackson2JsonRedisSerializer();final RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jackson);return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair).entryTtl(p.getTtl());}, (key1, key2) -> key2));}class CacheMap {private String name;private Duration ttl;public String getName() {return name;}public void setName(String name) {this.name = name;}public Duration getTtl() {return ttl;}public void setTtl(Duration ttl) {this.ttl = ttl;}}
}

2 Controller

package com.chenyun.web;import com.chenyun.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.TimeUnit;@RestController
public class TimeCacheController{@Autowiredprivate StringRedisTemplate redisTemplate;@PostMapping("getUserByIdTime")public User getUserByIdTime(){System.out.println("------------getUserById");User user1 = new User(1, "赵日天");//k v  t  uredisTemplate.opsForValue().set("user::1",user1.toString(),1, TimeUnit.MINUTES);return user1;}@Cacheable(value = "user#30s",key = "#id")@PostMapping("getUserByIdTime/{id}")public User getUserByIdTime(@PathVariable("id") Integer id){System.out.println("------------getUserById");User user1 = new User(1, "赵日天");User user2 = new User(2, "李杀神");User user3 = new User(3, "刘斩仙");if(id == 1){return user1;}else if(id == 2){return user2;}else if(id == 3) {return user3;}return null;}}

微服务架构-5-Redis实战-5-SpringBoot整合Redis缓存注解开发相关推荐

  1. 【仅售9.9元】石杉老师最新出品:C2C电商系统微服务架构120天实战训练营

    石杉老师最新出品:<C2C 电商系统微服务架构 120 天实战训练营>,长按扫描下方二维码了解: 微服务架构是当今架构领域最热的话题之一,也是互联网大厂必问的技术.掌握微服务架构技术栈相关 ...

  2. redis进阶之SpringBoot整合Redis(五)

    在聊 SpringBoot整合redis之前,我们先看看 Redis推荐的java连接开发工具:jedis知其然并知其所以然,授人以渔! 学习不能急躁,慢慢来会很快! Jedis 什么是Jedis 是 ...

  3. 【案例实战】SpringBoot整合Redis的GEO实现查找附近门店功能

    像我们平常美团点外卖的时候,都会看到一个商家距离我们多少米.还有类似QQ附近的人,我们能看到附近的人距离我们有多少米. 那么这些业务是怎么做的呢?是如何实现 基于位置的附近服务系统呢. 在去了解基于位 ...

  4. dubbo协议_阿里P8架构师谈微服务架构:Dubbo+Docker+SpringBoot+Cloud

    微服务架构 什么是微服务架构呢?简单说就是将一个完整的应用(单体应用) 按照一定的拆分规则(后文讲述)拆分成多个不同的服务,每个服务都能独立地进行开发.部署.扩展.服务于服务之间通过注入RESTful ...

  5. 亿级流量电商详情页系统实战:缓存架构+高可用服务架构+微服务架构

    <缓存架构+高可用服务架构+微服务架构>深入讲解了亿级流量电商详情页系统的完整大型架构.同时最重要的是,在完全真实的大型电商详情页系统架构下,全流程实战了整套微服务架构,包含了基于领域驱动 ...

  6. 基于 Docker 的微服务架构实践

    http://dockone.io/article/4887 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 DevOps,也见证了 Do ...

  7. docker容器 eureka 集成_微服务:基于 Docker 的微服务架构之分布式企业级实践参考...

    编者按:本文分享自CSDN技术博客,作者为 FlyWine,所有权归原著者.若有不妥,联系本头条号以做必要处理. 目录 Microservice 和 Docker 服务发现模式 客户端发现模式 Net ...

  8. 基于 Docker 的微服务架构

    基于 Docker 的微服务架构-分布式企业级实践 前言 Microservice 和 Docker 服务发现模式 客户端发现模式 Netflix-Eureka 服务端发现模式 Consul Etcd ...

  9. 【关于分布式系统开发和微服务架构自我心得小记

    一.一个完整项目为何要分布式开发? 完整项目业务实现是相当庞大,程序员在修改一个业务程序的的代码时,可能会影响整个项目的启动和部署,项目代码一个地方修改会产生很多问题,不利于程序的开发,同时项目的启动 ...

  10. 微服务架构最强讲解,那叫一个通俗易懂!

    作者:老_张 cnblogs.com/imyalost/p/6792724.html 目录如下: 一.微服务架构介绍 二.出现和发展 三.传统开发模式和微服务的区别 四.微服务的具体特征 五.SOA和 ...

最新文章

  1. java并行任务dispatch_Java模拟 双分派Double Dispatch
  2. python老鼠打洞问题_脑筋急转弯:老鼠为什么要打洞?这答案让人哭笑不得
  3. Codeforces 1027F. Session in BSU
  4. Boost::context模块fiber的throw测试程序
  5. 程序员数学基础【七、等比数列 棋盘麦粒】
  6. (转)解决fasterxml中string字符串转对象json格式错误问题(无引号 单引号问题)...
  7. 【数据库原理及应用】经典题库附答案(14章全)——第八章:数据库并发控制
  8. android自定义图片过渡效果,教你做出炫酷的Android动画效果
  9. mysql中删除数据库中的表格数据恢复_恢复从数据库中删除的表
  10. 【剑指Offer学习】【面试题66:矩阵中的路径】
  11. RemoteApp登录到特定的域
  12. 高性能Mysql(一)
  13. MFC程序设计——标尺的例子
  14. unity3d中的旋转
  15. 一文了解智能门锁的功能选购和安全性
  16. 性能服务器e5,英特尔至强E5服务器到底有多强?
  17. 计算 m 的 n 次幂
  18. 程序设计阶段性总结报告二
  19. SpringCloud中Feign进行服务调用 java.io.IOException: too many bytes written 问题解决
  20. 给你的web页面添加盲水印,附带检盲水印方案

热门文章

  1. 英特尔官方发布Atom N435芯片
  2. 英特尔推出功能强大的FPGA加速卡
  3. 中国氢氧化钡行业研究与投资战略报告(2021版)
  4. 说到产品需求,到底谁的是第一优先级?
  5. 类型多样的售楼处sketchup模型素材,速来收藏
  6. 花一周时间,啃完这套京东架构师独家微服务笔记,成功面进字节
  7. java用ftl模板循环导出word生成echarts图表折线图柱状图饼图横向表格竖向表格
  8. 计算机上机课程教学亮点,确保计算机课程多媒体教学质量,提高学生上机效率...
  9. 全年合辑 | 网安产业40万字报告,400页幻灯片,200项政策打包带走
  10. jq分页 不刷新页面_jquery无刷新分页