我正在使用WebFlux和WebClient,需要使用两个API并合并其响应。
第一个API接收类型和文档编号并返回一个列表,其中包含一个包含客户数据的元素(这就是它的定义方式)。
第二个API接收客户id并返回客户付款列表。
我需要使用这两个API并返回一个包含客户数据及其付款的实体。
API客户响应
public class CustomerResponseApi {
private List<CustomerApi> clientList;
}
public class CustomerApi {
private int customerId;
private String documentNumber;
private String documentType;
private String firstName;
private String lastName;
}
API付款响应
public class PaymentResponseApi {
private int customerId;
private LocalDate paymentDate;
private float amount;
private String paymentType;
}
最后我应该吃这个
CustomerResponse.java
public class CustomerResponse {
private int customerId;
private String documentNumber;
private String documentType;
private String firstName;
private String lastName;
private List<PaymentResponseApi> payments;
}
我有一个代理类负责进行API调用
CustomerProxy。Java语言
public class CustomerProxy {
@Value("${api.base-url}")
private String baseUrl;
public Mono<CustomerResponseApi> getCustomer(String documentType, String documentNumber) {
log.info("baseUrl: {}", baseUrl);
WebClient webClient = WebClient.create(baseUrl);
return webClient.get()
.uri(uri -> uri
.path("/customers")
.queryParam("documentNumber", documentNumber)
.queryParam("documentType", documentType)
.build()
)
.retrieve()
.bodyToMono(CustomerResponseApi.class);
}
}
付款代理。Java语言
public class PaymentProxy {
@Value("${api.base-url}")
private String baseUrl;
public Flux<PaymentResponseApi> getCustomerPayment(int customerId) {
log.info("baseUrl: {}", baseUrl);
WebClient webClient = WebClient.create(baseUrl);
return webClient.get()
.uri(uri -> uri
.path("/payments")
.queryParam("customerId", customerId)
.build()
)
.retrieve()
.bodyToFlux(PaymentResponseApi.class);
}
}
以及负责合并响应CustomerServiceImpl的服务。Java语言
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerProxy customerProxy;
@Autowired
private PaymentProxy paymentProxy;
@Override
public Mono<CustomerResponse> getCustomerAndPayments(String documentType, String documentNumber) {
return customerProxy.getCustomer(documentType, documentNumber).flatMap(resp -> {
CustomerApi customerApi = resp.getClientList().get(0); //always returns one customer
// Here is my problem, because getCustomerPayment method returns a Flux
List<PaymentResponseApi> payments = paymentProxy.getCustomerPayment(customerApi.getCustomerId());
CustomerResponseBuilder customerBuilder = CustomerResponse.builder()
.customerId(customerApi.getCustomerId())
.documentNumber(customerApi.getDocumentNumber())
.documentType(customerApi.getDocumentType())
.firstName(customerApi.getFirstName())
.lastName(customerApi.getLastName())
.payments(payments);
return Mono.just(customerBuilder.build());
});
}
}
在这种情况下,可以缓存第一次调用的结果,以防止调用API两次。
有时,通过创建一个包装类来不处理tuple,使用zip操作符也更容易。在这种情况下,需要付款的客户:
public class CustomerWithPayments {
private final CustomerApi customerApi;
private final List<PaymentResponseApi> paymentResponseApis;
}
缓存API结果的解决方案:
public Mono<CustomerResponse> getCustomerAndPayments(String documentType, String documentNumber) {
Mono<CustomerApi> customerMono = customerProxy.getCustomer(documentType, documentNumber)
.map(resp -> resp.getClientList().get(0))
.cache();
Mono<List<PaymentResponseApi>> paymentResponseMono = customerMono.map(CustomerApi::getCustomerId)
.flatMapMany(paymentProxy::getCustomerPayment)
.collectList();
return customerMono.zipWith(paymentResponseMono, CustomerWithPayments::new)
.map(customerWithPayments -> {
CustomerApi customer = customerWithPayments.getCustomerApi();
List<PaymentResponseApi> payments = customerWithPayments.getPaymentResponseApis();
return CustomerResponse.builder()
.customerId(customer.getCustomerId())
.documentNumber(customer.getDocumentNumber())
.documentType(customer.getDocumentType())
.firstName(customer.getFirstName())
.lastName(customer.getLastName())
.payments(payments)
.build();
});
}
解决此问题的两种方法:
public Mono<CustomerResponse> getCustomerAndPayments(String documentType, String documentNumber) {
return customerProxy.getCustomer(documentType, documentNumber)
.map(resp -> resp.getClientList().get(0))
.flatMap(customerApi -> {
Flux<PaymentResponseApi> paymentProxyFlux = paymentProxy.getCustomerPayment(customerApi.getCustomerId());
return paymentProxyFlux.collectList()
.map(payments -> {
CustomerResponseBuilder customerBuilder = CustomerResponse.builder()
.customerId(customerApi.getCustomerId())
.documentNumber(customerApi.getDocumentNumber())
.documentType(customerApi.getDocumentType())
.firstName(customerApi.getFirstName())
.lastName(customerApi.getLastName())
.payments(payments);
return customerBuilder.build();
});
});
}
因此,基本上使用Method od2您需要:
public Mono<CustomerResponse> getCustomerAndPayments(String documentType, String documentNumber) {
Mono<CustomerApi> customerApiMono = customerProxy.getCustomer(documentType, documentNumber)
.map(resp -> resp.getClientList().get(0));
Mono<List<PaymentResponseApi>> paymentResponseApiListMono = customerApiMono
.flatMapMany(customerApi -> paymentProxy.getCustomerPayment(customerApi.getCustomerId()))
.collectList();
return customerApiMono.zipWith(paymentResponseApiListMono)
.map(tuple -> {
CustomerApi customerApi = tuple.getT1();
List<PaymentResponseApi> payments = tuple.getT2();
CustomerResponseBuilder customerBuilder = CustomerResponse.builder()
.customerId(customerApi.getCustomerId())
.documentNumber(customerApi.getDocumentNumber())
.documentType(customerApi.getDocumentType())
.firstName(customerApi.getFirstName())
.lastName(customerApi.getLastName())
.payments(payments);
return customerBuilder.build();
});
}
方法2的缺点:Api1即客户API将被订阅两次。
问题内容: 如何将这两个JToken合并为一个JToken。听起来应该很简单,但无法解决。 谢谢您的帮助! 到目前为止,这是我尝试过的: 我首先将第一个对象分配给变量,然后尝试将其连接到第二个变量。我有一个循环,可以带回具有三个字段的多个页面。最终目标是抓取每个页面并创建一个包含所有页面的大J。 像这样的东西: 问题答案: 您可以用来将一个合并到另一个。请注意,可以控制数组的合并方式。从Enume
我有两个微服务,用户微服务和订单微服务。 因此客户端只需要调用一个endpointhttp://localhost:9090/api/getdetail 我们如何在API网关级别实现这一点?
问题内容: 结合这两个查询的正确语法是什么? 和 我试过了: 但我收到“ UNION和ORDER BY的用法不正确”。 编辑 此外,我希望结果在一行中返回。这样我就可以访问php中的值,例如 根据西蒙的建议,我不应该使用UNION,因为我想返回一行数据 问题答案: 您不能先进入,然后再进入。 编辑 但是你可以 将ORDER BY或LIMIT应用于单个SELECT,将子句放在包围SELECT的括号内
我已经开始编写两个web应用程序项目 使用Spring REST API的移动客户端的RESFful API 我的问题是,两个Web应用程序都使用相同的数据库,我认为,而不是有两个Web应用程序,我实际上应该开始这个项目,只使用一个Web应用程序来处理Web和移动客户端的请求。 我现在遇到的问题是,我不知道如何“合并”这两个家伙,以及我是否应该坚持使用Spring RESTAPI,或者是否应该使用
问题内容: 如何合并这两个SQL语句? 两个表中都存在hits10,hits11和hits12。 问题答案: 使用UNION查询-只需在两个查询之间填入“ UNION”即可: 更新 将联合包装在另一个查询中:
我有两个(或更多)