Spring Boot如何基于返回结果实现@Cacheable条件缓存
报错原因梳理
- 第一种写法仅判断了
result属性为null的场景,未覆盖空集合的情况,完全不符合需求。 - 第二种、第三种写法报错是由SpEL表达式解析规则导致的:
- 直接写
.size时,SpEL会默认将其作为JavaBean属性解析,寻找对应的getSize()方法,但JDK的ArrayList没有getSize()方法,只有size()实例方法,因此抛出属性不存在的异常。 .length是Java数组的固有属性,List属于集合框架类而非数组,自然也会抛出属性不存在的异常。
- 直接写
- 额外前提:必须保证
Response类中的result属性有public修饰的getResult()方法,否则SpEL无法解析到该属性,会直接报错。 - 你给出的业务代码示例有笔误:
save方法最后缺少return new Response(result);语句,否则编译不通过,无法运行。
正确配置方案
我们的需求是「仅当result属性既不为null、也不是空集合时才缓存」,对应unless的逻辑是:当result为null,或者result集合为空时,不执行缓存。
可使用以下两种可运行的写法:
- 调用List原生
size()方法判断
@Cacheable(value = "saveCache", key = "{#a, #b, #c}", unless="#result.result == null || #result.result.size() == 0") public Response save(String a, String b, String c) { // 业务逻辑块 List<Map<String, Object>> result = new ArrayList(); return new Response(result); }
- 调用List原生
isEmpty()方法判断(更简洁)
@Cacheable(value = "saveCache", key = "{#a, #b, #c}", unless="#result.result == null || #result.result.isEmpty()") public Response save(String a, String b, String c) { // 业务逻辑块 List<Map<String, Object>> result = new ArrayList(); return new Response(result); }
优化写法:使用SpEL安全导航操作符
?.简化空判断,避免额外的null判断逻辑,等价于上面的写法:unless="#result.result == null || #result.result?.isEmpty()"
内容的提问来源于stack exchange,提问作者Galet
相关产品推荐
相关产品推荐

