如何在Spring @Cacheable注解中引用枚举类型
问题
我有一个Spring Boot项目,希望对调用远程接口返回的结果实现缓存,但并非缓存所有结果,而是仅满足特定条件时缓存。具体来说,调用的接口返回的结果对象包含一个枚举(MyStatus),用于标识请求是否成功,我希望仅在结果成功(MyStatus.OK)时缓存该结果。
在常规代码中,我会用如下条件判断:
if(result.status == MyStatus.OK)
但这种写法在@Cacheable注解中无法生效。我知道需要将条件写在unless参数中,但尝试写入类似如下条件时:
@Cacheable(value = 'myCacheName', key = "#myKey", unless = "#result.status() != MyStatus.OK")
却出现错误“Cannot resolve class 'MyStatus'”。请问这种需求是否可行?如果可行,正确的写法是什么?
解决方案
这个需求完全可行,出现错误的原因是SpEL表达式中无法直接引用枚举类名,需要通过特定语法来访问枚举类型。下面提供两种正确的写法:
写法一:使用枚举的全限定类名
在SpEL中,需要通过T()语法来引用Java类,所以你需要把枚举的全限定类名(包路径+类名)填入T()中,示例如下:
@Cacheable(value = "myCacheName", key = "#myKey", unless = "#result.status != T(com.your.package.MyStatus).OK")
注意替换com.your.package.MyStatus为你项目中MyStatus枚举实际的全限定类名。
写法二:直接判断枚举的字符串标识
如果你的枚举MyStatus的name()方法返回的字符串是"OK"(默认枚举的name()就是枚举常量名),也可以直接通过字符串比较来判断,这样不需要引用枚举类,写法更简洁:
@Cacheable(value = "myCacheName", key = "#myKey", unless = "#result.status.name() != 'OK'")
逻辑说明
@Cacheable的unless参数逻辑是:当表达式结果为true时,不缓存当前结果。所以我们的表达式要表达“结果状态不是OK时不缓存”,这样当状态为OK时,表达式结果为false,就会触发缓存;状态非OK时,表达式结果为true,跳过缓存,正好符合你的需求。
内容的提问来源于stack exchange,提问作者Kira Resari

