【问题标题】:How to use cache on controller/service in spring boot?如何在 Spring Boot 中使用控制器/服务上的缓存?
【发布时间】:2019-11-19 21:41:52
【问题描述】:

我正在尝试按照https://www.java4s.com/spring-boot-tutorials/how-to-configure-cache-in-spring-boot-applications/ 上的说明在我的 spring-boot 应用程序上添加缓存,但它不起作用。我不完全确定如何测试它。我在本文中的控制器下有一个 system.out.print。如果缓存有效,那么它只会打印一次“test”,但会从具有相同输入的请求中返回相同的结果。我的代码如下:

CurrencyController.java

    @RequestMapping(method = RequestMethod.POST)
    @Cacheable(value="currency")
    public ResponseEntity getExchangedCurrency(final @RequestBody CurrencyExchange currencyExchange) {
        System.out.println("Test");
        return ResponseEntity.ok()
              .headers(responseHeaders)
              .body(currencyService.calculate(currencyExchange));
    }

App.java

@SpringBootApplication
@EnableCaching
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);



    }
}

【问题讨论】:

    标签: java spring-boot spring-cache


    【解决方案1】:

    @Cacheable 注解的工作方式是默认使用方法参数作为缓存映射的键。在这种情况下,currencyExchange 对象。由于它是每个请求中的对象,因此 spring 请求调度程序会创建新对象,并且缓存管理器会保留为单独的键。

    Req1 -> object1 -> map.put(object1, response)

    Req2 -> object2 -> map.contains(object2) -> false -> map.put(object2, 回复)

    如果您认为所有的 post 请求都从缓存中发送相同的响应(并非总是如此),您可以像这样更改密钥。

    @RequestMapping(method = RequestMethod.POST)
    @Cacheable(value="currency", key="#root.method")
    public ResponseEntity getExchangedCurrency(final @RequestBody CurrencyExchange currencyExchange) {
        System.out.println("Test");
        return ResponseEntity.ok()
              .headers(responseHeaders)
              .body(currencyService.calculate(currencyExchange));
    }
    

    您也可以使用 Spring 表达式语言 (SpEL) 表达式来定义键,如果您的 currencyExchange 有方法 getId() 可以用作潜在的缓存键,您可以这样做

    @Cacheable(value="currency", key="#root.args[0].getId()")
    

    清除缓存在spring boot主类上添加@EnableCaching,fixedDelay以毫秒为单位

    @CacheEvict(allEntries = true, value = {"currency"})
    @Scheduled(fixedDelay = 5000 ,  initialDelay = 5000)
    public void clearCache() {
        System.out.println("Cache cleared");
    }
    

    【讨论】:

    • 感谢您的回复。在 CurrencyExchange 中有 3 个属性:来源、目标和价值。是否有可能拥有结合所有这 3 个值的键?我使用了这个表达式并且它有效,但我不确定这是否是正确的方法。 @Cacheable(value="currency", key="#root.args[0].getSource() + #root.args[0].getTarget() + #root.args[0].getValue()") 。另一个问题是如何使缓存在指定的时间内过期? @Pasupathi Rajamanickam
    • @ChandaraChea 是的,你可以像你说的那样实现你的密钥,清除缓存,更新答案。
    • 我怀疑 RequestMapping 方法是否会被直接缓存。原因是因为 Spring Cache 的工作原理是构建代理类的单例对象,该代理类构建在具有 @Caheable 注释的当前类之上。在运行时,我怀疑 Spring 是否能够调用 Singleton Cache。相反,它可能正在创建控制器的实例,从而跳过缓存。我认为您应该在单独的方法和调用上构建缓存,而不是缓存 RequestMapping 方法。让我们随时了解您的发现。
    • @SriniM 你是对的,如果我们使用ehCache spring-cache 在@RequestMapping 上使用@Cacheable 确实可以正常工作
    猜你喜欢
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 2019-03-20
    • 2016-12-31
    • 2021-12-07
    • 2019-01-18
    相关资源
    最近更新 更多