SpringBoot @Cacheable缓存注解的使用

1. 引入缓存依赖

		<!---->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        
        <!--这边用的是Redis缓存,所以加上这个依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2. application.properties 配置

spring:
  cache:
    type: redis
  redis:
    database: 5
    host: 192.168.25.129
    port: 6379
    password: 123456

3. 准备基本的Controller、Service代码

public interface RedisService {
    String getString(String name);
}
@Service
public class RedisServiceImpl implements RedisService {
    @Override
    public String getString(String name) {
        return "hello " + name;
    }
}
@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    private RedisService redisService;

    @RequestMapping("/getString1")
    public String getString1(@RequestParam String name){
        return redisService.getString(name);
    }
}

4. @Cacheable注解

4.1 cacheNames和value

指定缓存的名字,可以通过数组的方式指定多个缓存。

    @AliasFor("cacheNames")
    String[] value() default {};

    @AliasFor("value")
    String[] cacheNames() default {};

修改前面的代码,在ServiceImpl的方法上,加上@Cacheable注解并指定value属性

    @Override
    @Cacheable(value = {"REDIS:GETSTRING1"})
    public String getString(String name) {
        return "hello " + name;
    }

运行SpringBoot程序,在浏览器输入 http://localhost:99/redis/getString1?name=fuhb,然后查看Redis缓存确认是否生成对应的key

127.0.0.1:6379[5]> KEYS *
1) "REDIS:GETSTRING1::fuhb"

由此可见,默认会以 value + 参数的格式生成 Redis Key。

如果是多个参数的情况下,Redis Key会是什么格式呢?

    @RequestMapping("/getString2")
    public String getString2(@RequestParam String name){
        return redisService.getString(name, "test");
    }
    @Override
    @Cacheable(value = {"REDIS:GETSTRING2"})
    public String getString(String name, String tag) {
        return tag + " " + name;
    }

同样的,在浏览器输入 http://localhost:99/redis/getString2?name=fuhb,再查看Redis Key信息

127.0.0.1:6379[5]> KEYS *
1) "REDIS:GETSTRING2::SimpleKey [fuhb,test]"
2) "REDIS:GETSTRING1::fuhb"

由此可见,参数以 SimpleKey [参数拼接] 的格式进行组合。所以,接下来讲一下 key 和 keyGenerator 属性的使用

4.2 key 和 keyGenerator

keyGenerator

SpringBoot默认使用的是SimpleKeyGenerator生成key,其生成规则如下:

  • 当参数为空时,返回空
  • 当参数只有一个时,返回第一个参数的值
  • 当参数大于一个时,返回SimpleKey对象,其序列化格式上面讲过了,代码比较简单
    public String toString() {
        return this.getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";
    }

如果需要自定义KeyGenerator,可以参考这篇文章:@Cacheable自定义KeyGenerator

key

相较于keyGenerator,官方更推荐直接显示地指定key

    @Override
    @Cacheable(value = {"REDIS:GETSTRING3"}, key = "#tag + #name")
    public String getString4(String tag, String name) {
        return tag + " " + name;
    }

或者用这种写法,p0、p1来替代参数名

    @Override
    @Cacheable(value = {"REDIS:GETSTRING4"}, key = "#p0 + #p1")
    public String getString4(String tag, String name) {
        return tag + " " + name;
    }

key 和 keyGenerator 参数是互斥的,不能同时使用

4.3 cacheManager 和 cacheResolver

CacheManager,缓存管理器是用来管理(检索)一类缓存的。通常来讲,缓存管理器是与缓存组件类型相关联的。我们知道,spring 缓存抽象的目的是为使用不同缓存组件类型提供统一的访问接口,以向开发者屏蔽各种缓存组件的差异性。那么 CacheManager 就是承担了这种屏蔽的功能。spring 为其支持的每一种缓存的组件类型提供了一个默认的 manager,如:RedisCacheManager 管理 redis 相关的缓存的检索、EhCacheManager 管理 ehCache 相关的缓等。

CacheResolver,缓存解析器是用来管理缓存管理器的,CacheResolver 保持一个 cacheManager 的引用,并通过它来检索缓存。CacheResolver 与 CacheManager 的关系有点类似于 KeyGenerator 跟 key。spring 默认提供了一个 SimpleCacheResolver,开发者可以自定义并通过 @Bean 来注入自定义的解析器,以实现更灵活的检索。

大多数情况下,我们的系统只会配置一种缓存,所以我们并不需要显式指定 cacheManager 或者 cacheResolver。但是 spring 允许我们的系统同时配置多种缓存组件,这种情况下,我们需要指定。指定的方式是使用 @Cacheable 的 cacheManager 或者 cacheResolver 参数。

4.4 sync

sync=true表示同步,也就是缓存的入口将被锁住,直到上一个线程的操作完成,可以避免缓存击穿的问题。默认情况是false,也就是异步访问,初始状态下缓存不存在,如果有大量的线程同时访问,会因为没有缓存而对DB造成较大压力。

4.5 condition

缓存的条件,只有当condition返回结果为true才使用缓存。该配置支持SpEL表达式,也可以使用result表示取返回值

如下例子,只有当name的值等于admin时,才会构造并使用缓存

    @Override
    @Cacheable(value = {"REDIS:GETSTRING5"}, key = "#p0 + #p1", condition = "#name == 'admin'")
    public String getString5(String tag, String name) {
        return tag + " " + name;
    }

4.6 unless

不使用缓存的条件,跟上面的condition相反

如下例子,当name的值等于admin时不使用缓存

    @Override
    @Cacheable(value = {"REDIS:GETSTRING6"}, key = "#p0 + #p1", unless = "#name == 'admin'")
    public String getString6(String tag, String name) {
        return tag + " " + name;
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中,可以使用自定义注解来实现加密功能。首先,你需要定义一个自定义注解,比如`@Encrypt`。然后,你可以在需要加密的方法或字段上使用这个注解。接下来,你可以使用反射机制来获取被注解的方法或字段,并在运行时对其进行加密操作。 下面是一个简单的示例代码,演示了如何使用自定义注解实现加密功能: ```java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface Encrypt { } public class Encryptor { public static String encrypt(String data) { // 实现加密逻辑 return "encrypted_" + data; } } public class MyClass { @Encrypt private String sensitiveData; public void processSensitiveData() { // 获取所有字段 Field\[\] fields = this.getClass().getDeclaredFields(); for (Field field : fields) { // 检查字段是否被@Encrypt注解修饰 if (field.isAnnotationPresent(Encrypt.class)) { try { // 设置字段可访问 field.setAccessible(true); // 获取字段的值 String value = (String) field.get(this); // 对字段的值进行加密 String encryptedValue = Encryptor.encrypt(value); // 设置加密后的值 field.set(this, encryptedValue); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } } ``` 在上面的示例中,`@Encrypt`注解被用于修饰`sensitiveData`字段。在`processSensitiveData`方法中,通过反射获取被注解的字段,并对其进行加密操作。你可以根据实际需求修改加密逻辑和注解使用方式。 请注意,这只是一个简单的示例,实际的加密操作可能需要更复杂的算法和逻辑。同时,加密操作涉及到数据的安全性,建议在实际应用中使用专业的加密库和算法来保证数据的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

°Fuhb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值