@Cacheable 在控制器中工作,但不在服务内部工作

nic*_*net 2 redis spring-boot spring-cache spring-restcontroller

我在 Spring Boot 中遇到这个奇怪的问题,@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是@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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

g00*_*00b 5

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

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

我假设您想要缓存除 之外的每个值null,但在这种情况下您必须反转您的条件,例如:

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

或者,正如评论中提到的,您可以使用conditionin 代替unless

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

  • 您还可以将“unless”重命名为“condition”并保留您所拥有的内容以使意图更加清晰 (4认同)