基于注解方式缓存本地数据

一、简介

之前一直在忙,没有时间写一篇基于注解的缓存本地数据,因为有的小的业务没必要引入redis中间件,所以我个人觉得还是得根据自己的业务场景去使用。

二、实战代码

1.引入依赖

	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
	<dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
        <version>2.9.0</version>
	</dependency>

2.springboot启动类需要启用注解

@SpringBootApplication
@EnableCaching //显式开启cache缓存
public class CacheApplication {

	public static void main(String[] args) {
		SpringApplication.run(CodeApplication.class, args);
	}

}

3.自定义Cache注解

@AllArgsConstructor
@Getter
public enum CacheType {

    /*
       新增缓存方法步骤:
       1. 在CacheType中新增缓存类型 (会自动创建缓存器) --> 也可以不定义新的缓存器 共用已经存在的缓存器 但要注意key的生成方式 避免key冲突
       2. 在需要缓存的方法上加入 @Cacheable注解 并给@Cacheable注解 设置步骤1中的缓存名称 及 指定缓存key生成方式

       缓存具体执行步骤:
       1.会先根据key去缓存中找缓存
       2.若找到缓存 则直接返回缓存中的数据 不会执行@Cacheable注解方法下的代码
         若没有找到缓存 则会执行方法中的代码 然后将方法的返回结果进行缓存 key为@Cacheable注解中的key指定方式生成 value为方法的返回值

       提示:
       1. 若在同一个类中调用缓存方法 请使用AOP代理 否则无法使用缓存
       2. @Cacheable: 若缓存存在,则使用缓存;不存在,则执行方法,并将结果存入缓存
          @CacheEvit: 失效缓存(等于删除缓存)
          @CachePut: 更新缓存(不管缓存存不存在,都会执行方法,然后更新缓存)
     */
	
    //将过期时间设置为30s,方便我们测试
    USER_CACHE("用户缓存", "userCache", 30, TimeUnit.SECONDS, 500, 1000);


    /**
     * 描述
     */
    private String description;

    /**
     * 缓存名称
     */
    private String cacheName;

    /**
     * 过期时间
     */
    private long expireTime;

    /**
     * 时间单位
     */
    private TimeUnit timeUnit;

    /**
     * 初始容量
     */
    private int initialCapacity;

    /**
     * 最大缓存数量
     */
    private long maximumSize;
}

4.caffeine基本配置

@Configuration
public class Config {

    @Bean
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> caffeines = new ArrayList<CaffeineCache>();
        for (CacheType type : CacheType.values()) {
            CaffeineCache caffeineCache = new CaffeineCache(type.getCacheName(),
                    Caffeine.newBuilder()
                            //初始容量
                            .initialCapacity(type.getInitialCapacity())
                            //最大容量
                            .maximumSize(type.getMaximumSize())
                            //过期时间
                            .expireAfterWrite(type.getExpireTime(), type.getTimeUnit()).build());;
            caffeines.add(caffeineCache);
        }
        cacheManager.setCaches(caffeines);
        return cacheManager;
    }
}

5.测试

5.1 Entity
@Data
@Builder
public class User {

    private String name;

    private Integer age;

}
5.2 Controller
@RestController
@RequestMapping
public class Controller {

    @Resource
    private UserService userService;

    /**
     * @param id id
     * @return {@link User }
     * @Description 演示获取用户并进行缓存
     * @Date 2023/04/02 22:16
     */
    @GetMapping("getUser")
    public User getUser(@RequestParam Integer id) {
        //循环10次,看控制台会不会打印十次user信息
        for (int i = 0; i < 10; i++) {
            User user = userService.getUser(id);
        }
        return userService.getUser(id);
    }

    /**
     * @param id id
     * @return {@link User }
     * @Description 观看缓存
     * @Author mouyang
     * @Date 2023/04/02 22:17
     */
    @GetMapping("watchCache")
    public User watchCache(@RequestParam Integer id) {
        return userService.watchCache(id);
    }
}
5.3 Service
public interface UserService {

    User getUser(Integer id);

    User watchCache(Integer id);
}
5.3 ServiceImpl
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private CacheManager cacheManager;

    @Override
    @Cacheable(cacheNames = "userCache", key = "#id")
    public User getUser(Integer id) {
        User user = User.builder()
                .name("张三")
                .age(23)
                .build();
        System.out.println("获得user: " + user);
        return user;
    }

    @Override
    public User watchCache(Integer id) {
        Cache cache = cacheManager.getCache(CacheType.USER_CACHE.getCacheName());
        Cache.ValueWrapper valueWrapper = cache.get(id);
        User user = (User) valueWrapper.get();
        System.out.println("从缓存中获取到id为+" + id + "的+user:" + user);
        return user;
    }
}
5.4 调用缓存方法二次
GET http://localhost:8080/getUser?id =1

多次调用结果会显示出:从缓存中获取到id为+1的+user:User(name=张三, age=23)
这样就实现了缓存的调用,只要缓存数据没有过期,都可以在不同接口中共用

6.Cachable 添加缓存注解的一些参数介绍

@Cacheable 是 Spring Framework 中的一个注解,它可以应用在方法上,用于声明该方法的结果可以被缓存起来,以便后续的调用可以直接返回缓存中的结果,而不必真正执行方法的代码。

@Cacheable 注解中的参数有以下几个:

value:缓存的名称,可以是一个字符串数组,表示该方法的结果可以被缓存到哪些缓存中。默认值为一个空数组,表示缓存到默认的缓存中。
key:缓存的 key,可以是一个 SpEL 表达式,表示缓存的 key 可以根据方法参数动态生成。默认值为一个空字符串,表示使用默认的 key 生成策略。
condition:缓存的条件,可以是一个 SpEL 表达式,表示缓存的结果是否应该被缓存。默认值为一个空字符串,表示不考虑任何条件,缓存所有结果。
unless:缓存的排除条件,可以是一个 SpEL 表达式,表示缓存的结果是否应该被排除在缓存之外。默认值为一个空字符串,表示不排除任何结果。

6.1 @Cacheable高级用法

1.指定缓存的key

@Cacheable(value = "myCache", key = "#id")
public String myMethod(int id) {
    // ...
}

2.指定缓存条件

@Cacheable(value = "myCache", condition = "#result != null")
public String myMethod() {
    // ...
}

3.指定缓存的过期时间

@Cacheable(value = "myCache", key = "#id", expire = 3600)
public String myMethod(int id) {
    // ...
}

7. @CacheEvict注解,清除缓存参数介绍

value:缓存位置名称,不能为空,同上
key:缓存的key,默认为空,同上
condition:触发条件,只有满足条件的情况才会清除缓存,默认为空,支持SpEL
allEntries:true表示清除value中的全部缓存,默认为false

7.1 清除所有缓存

  @CacheEvict(value="users", allEntries=true)
   public void delete(Integer id) {
   }

7.2 清除掉指定key的缓存

  @CacheEvict(value="andCache",key="#user.userId + 'findById'")  
    public void modifyUserRole(SystemUser user) { 
    }

7.3 清除掉全部缓存

  @CacheEvict(value="andCache",allEntries=true)  
   public final void setReservedUsers(String[] reservedUsers) {  
   }

8.@CachePut 更新缓存

value		缓存的名称,在 spring 配置文件中定义,必须指定至少一个
		@CachePut(value=”my cache”)
key		缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合
		@CachePut(value=”testcache”,key=”#userName”)
condition	缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存
		@CachePut(value=”testcache”,condition=”#userName.length()>2”)

8.1 更新缓存

@CachePut(value="accountCache",key="#account.getName()")// 更新accountCache 缓存
public Account updateAccount(Account account) { 
  return updateDB(account); 
}

本文部分数据参考:原文链接:https://blog.csdn.net/weixin_51389615/article/details/129918956

posted @ 2024-03-27 16:02  牛奶配苦瓜  阅读(52)  评论(0)    收藏  举报