💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 依赖 ~~~ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> ~~~ Spring Cache 是在 Spring 3.1 中引⼊的基于注释(Annotation)的缓存(Cache)技术,它本质上不是⼀个 具体的缓存实现⽅案,⽽是⼀个对缓存使⽤的抽象,通过在既有代码中添加少量它定义的各种 Annotation, 即能够达到缓存⽅法的返回对象的效果 利⽤了 Spring AOP 的动态代理技术,在项⽬启动的时候动态⽣成它的代理类,在代理类中实现了对应的逻辑 # 缓存注解详解 * @CacheConfig:设置类级别上共享的一些常见缓存设置 * @Cacheable:触发缓存写入 * @CacheEvict:触发缓存清除 * @Caching 将多种缓存操作分组 * @CachePut:更新缓存(不会影响到方法的运行) ## @Cacheable **需要注意的是当⼀个⽀持缓存的⽅法在对象内部被调⽤时是不会触发缓存功能的** 添加在方法上,根据条件添加缓存 * value: 缓存的名称,不能为空 * cacheNames: 缓存的名称,和value二选一 * key: 缓存的key,默认为空, 如果指定要按照 SpEL 表达式编写;如果不指定,则缺省按照⽅法的所有参数进⾏组合 * keyGenerator: 指定key的生成策略 * cacheManager: 指定缓存管理器 * cacheResolver: 指定获取解析器 * condition: 条件符合则缓存, 默认为空,既表示全部都加⼊缓存,⽀持SpEL * unless: 条件符合则不缓存 * sync: 是否使用异步模式 默认false **保存方法缓存结果** ~~~ @Cacheable(value = "index", condition = "#name.length() <= 4") @RequestMapping(value = "/index", method = RequestMethod.GET) public String index(String name) { System.out.println("没有走缓存"); return "hello world"; } ~~~ 输入url: [http://127.0.0.1:10010/index?name=11](http://127.0.0.1:10010/index?name=11) 第⼀次输出栏输出:没有⾛缓存! 再次执⾏⽆输出,表明已经⾛缓存 然后把name参数改大于4个字符,他就走缓存了 **缓存数据库** 一般用于查询操作,根据key查询缓存. 1. 如果key不存在,查询db,并将结果更新到缓存中。 2. 如果key存在,直接查询缓存中的数据。 ~~~ @RequestMapping("/getUsers") @Cacheable(value="usersCache",key="#nickname",condition="#nickname.length() >= 6") public List<User> getUsers(String nickname) { List<User> users=userRepository.findByNickname(nickname); System.out.println("执⾏了数据库操作"); return users; } ~~~ Spring ⾸先检查 condition 条件是否满⾜,如 果不满⾜,执⾏⽅法,返回;如果满⾜,在缓存空间中查找使⽤ key 存储的对象,如果找到,将找到的结果 返回,如果没有找到执⾏⽅法,将⽅法的返回值以 key-value 对象的⽅式存⼊缓存中,然后⽅法返回 ## @CachePut 可以标注在类上和⽅法上 * value 缓存的名称 * key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照⽅法的所有参数进⾏组合 * condition 缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才进⾏缓存 @Cacheable没有缓存数据会执行方法后,把结果缓存起来,第二次调用方法不执行方法,直接从缓存中获取数据并返回. @CachePut每次都会执行方法,不管缓存中有没有数据,都会把结果缓存. ~~~ //修改数据后更新缓存 @Override @CachePut(cacheNames = "cacheManager", key = "'USER:'+#updateUser.id", unless = "#result == null") public User updateUser(User updateUser) { return repository.save(updateUser); } ~~~ ## @CacheEvict 用来标注在需要清除缓存元素的⽅法或类上的,当标记在⼀个类上时表示其中所有的⽅法的 执⾏都会触发缓存的清除操作. 根据key删除缓存中的数 添加在方法上,根据条件清空缓存 * value: 缓存名称,不能为空 * cacheNames: 缓存的名称,与value二选一 * keyGenerator: key的生成器。key/keyGenerator二选一使用 * condition: 触发条件,支持SpEL * allEntries: true表示清除value中的全部缓存,默认为false * beforeInvocation: 清除操作默认是在对应⽅法成功执⾏之后触发的,即⽅法如果因为抛出异常⽽未能成功返回时也不会触发清 除操作。使⽤ beforeInvocation 可以改变触发清除操作的时间,当我们指定该属性值为 true 时,Spring 会在 调⽤该⽅法之前清除缓存中的指定元素 * cacheManager: 指定缓存管理器 * cacheResolver: 或者指定获取解析器 value 表示清除操作是发⽣在哪些 Cache 上的(对应 Cache 的名称); key 表示需要清除的是哪个 key, 如未指定则会使⽤默认策略⽣成的 key; condition 表示清除操作发⽣的条件 ~~~ //将所有以 usersCache 为名的缓存全部清除 @RequestMapping("/allEntries") @CacheEvict(value="usersCache", allEntries=true) public List<User> allEntries(String nickname) { List<User> users=userRepository.findByNickname(nickname); System.out.println("执⾏了数据库操作"); return users; } ~~~ ## @CacheConfig 作用在类上,为本类的缓存注解配置全局属性 * cacheNames: 缓存名称 * keyGenerator: key的生成器 * cacheManager: 缓存管理器 * cacheResolver: 获取解析 ~~~ //UserServiceImpl的所有缓存注解例如@Cacheable的value值就都为user @CacheConfig(cacheNames = "user") @Service publicclass UserServiceImpl implements UserService {} ~~~ ## @Caching 组合多个缓存注解 ~~~ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Caching { Cacheable[] cacheable() default {}; CachePut[] put() default {}; CacheEvict[] evict() default {}; } ~~~ # 配置CacheManager 整合redis那有配置