@Cacheable 在 Controller 中工作,但不在服务内部

@Cacheable is working in Controller but not inside service

我在 Spring 引导中遇到了这个奇怪的问题,其中 @Cacheable 在控制器中工作但不在服务内部。我可以在 Redis 中看到 GET 调用,但看不到 PUT 调用。

这是有效的,因为它在控制器中

@RestController
@RequestMapping(value="/places")
public class PlacesController {

    private AwesomeService awesomeService;

    @Autowired
    public PlacesController(AwesomeService awesomeService) {
        this.awesomeService = awesomeService;
    }

    @GetMapping(value = "/search")
    @Cacheable(value = "com.example.webservice.controller.PlacesController", key = "#query", unless = "#result != null")
    public Result search(@RequestParam(value = "query") String query) {
        return this.awesomeService.queryAutoComplete(query);
    }
}

但是当我在 Service 中这样做时 @Cacheable 不工作

@Service
public class AwesomeApi {

    private final RestTemplate restTemplate = new RestTemplate();

    @Cacheable(value = "com.example.webservice.api.AwesomeApi", key = "#query", unless = "#result != null")
    public ApiResult queryAutoComplete(String query) {
        try {
            return restTemplate.getForObject(query, ApiResult.class);
        } catch (Throwable e) {
            return null;
        }
    }
}

我可以在 Redis 中看到 GET 调用,但看不到 PUT 调用。

您的缓存应该可以正常工作。请确保您有 @EnableCaching 注释并且您的 unless 标准是正确的。

现在,您正在使用 unless="#result != null",这意味着它将缓存结果,除非它不是 null。这意味着它几乎永远不会缓存,除非 restTemplate.getForObject() returns null,或者发生异常时,因为那时你也会返回 null.

我假设你想缓存每个值,除了 null,但在那种情况下你必须反转你的条件,例如:

@Cacheable(
    value = "com.example.webservice.api.AwesomeApi",
    key = "#query",
    unless = "#result == null") // Change '!=' into '=='

或者,,而不是反转条件,你可以使用 condition 代替 unless:

@Cacheable(
    value = "com.example.webservice.api.AwesomeApi",
    key = "#query",
    condition = "#result != null") // Change 'unless' into 'condition'