首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹簧引导反应式缓存

弹簧引导反应式缓存
EN

Stack Overflow用户
提问于 2022-03-18 19:38:03
回答 1查看 2.6K关注 0票数 2

在我的应用程序中,我使用的是spring网络流量,我使用webclient从一些第三方API中检索细节。现在,我想将第一次webClient响应存储在内存缓存中,以便第二次能够直接从缓存中获得这些响应。我试图在内存缓存机制和"caffine“中使用Spring引导。但没有一个像预期的那样起作用。application.yml:

代码语言:javascript
复制
spring:
 cache:
  cache-names: employee
 caffiene:
  spec: maximumSize=200, expireAfterAccess=5m

EmployeeApplication.java:

代码语言:javascript
复制
@SpringBootApplication
@EnableCaching
public class EmployeeApplication{
   public static void main(String[] args){
    
}
}

EmployeeController.java:有一个rest端点employee/all,它从第三方Api中获取所有雇员。EmployeeService.java:

代码语言:javascript
复制
@Service
@Slf4j
public class EmployeeService{
  @Autowired
  private WebClient webClient;
  @Autowired
  private CacheManager cacheManager;
  @Cacheable("employee")
  public Mono<List<Employee>> getAllEmployee(){
    log.info("inside employee service {}");
    return webClient.get()
        .uri("/employees/")
        .retrieve()
        .bodyToMono(Employee.class);
}
}

虽然我已经配置了缓存名,但是当我第二次访问url时,它正在调用服务方法。需要使用什么缓存机制来缓存Mono响应?请建议一下。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-18 22:41:16

缓存反应性发布者有几种选择。

  1. 使用反应性cache API在定义的持续时间内缓存Mono
代码语言:javascript
复制
employeeService.getAllEmployee()
    .cache(Duration.ofMinutes(60))
    .flatMap(employees -> {
        // process data
    })
  1. 使用外部缓存与咖啡因。

咖啡因支持基于CompletableFuture的异步缓存,可以很容易地适应反应性API。

代码语言:javascript
复制
AsyncLoadingCache<String, List<Employee>> cache = Caffeine.newBuilder()
    .buildAsync((tenant, executor) ->
            employeeService.getAllEmployee(tenant).toFuture()
    );


Mono<List<Employee>> getEmployee(String tenant) {
    return Mono.fromCompletionStage(clientCache.get(tenant));
}
  1. 使用外部缓存与番石榴和CacheMonoreactor-extra。如果需要根据不同的输入(例如,多租户环境)缓存结果,则此选项更适合。

UPDATE:自反应堆-额外3.4.7以来,CacheMono已被废弃。最好使用#2与咖啡因一起使用外部缓存。

下面是番石榴的一个例子,但您可以将其修改为CacheManager

代码语言:javascript
复制
Cache<String, List<Employee>> cache = CacheBuilder.newBuilder()
        .expireAfterWrite(cacheTtl)
        .build();


Mono<List<Employee>> getEmployee(String tenant) {
    return CacheMono.lookup(key -> Mono.justOrEmpty(cache.getIfPresent(key)).map(Signal::next), tenant)
            .onCacheMissResume(() -> employeeService.getAllEmployee(tenant))
            .andWriteWith((key, signal) -> Mono.fromRunnable(() ->
                            Optional.ofNullable(signal.get())
                                    .ifPresent(value -> cache.put(key, value))
                    )
            );
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71532361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档