我有一个简单的用例,不确定如何做,因为我是spring webflux的新手。
我正在使用spring boot webflux starters
。
我需要呼叫2个端点。让我们说Endpoint1
和Endpoint2
。
每当有一个请求命中Endpoint1
时,我都应该先以相同的请求命中Endpoint2
并使用Endpoint2
的响应来丰富原始请求,然后再做进一步的处理。
在执行任何操作之前,需要使用Endpoint1
的响应来丰富Endpoint2
的请求对象。如何使用Spring webflux强制执行此命令?在我的情况下,原始请求对象在进一步使用之前并未得到充实。任何帮助,对此深表感谢!
仅供参考-使用Endpoint2
完成对webclient
的调用
public Mono<Response1> endpoint1(Request1 request1){
Flux<Response2> reponse2 = webclient.getEndpoint2(request1); // Returns a Flux
//use the above reponse2 to enrich the request1
return webclient.getSomething(request1); //Returns Mono<Response1>
}
public Mono<ApplicationResponse> save(ApplicationRequest request) {
return Mono.subscriberContext().flatMap(ctx -> {
Mono blockingWrapper = Mono.fromCallable(() ->
service.getId(request)
.subscriberContext(ctx)
.subscribe(id -> request.setId(id))
).subscribeOn(Schedulers.elastic());
return blockingWrapper.flatMap(o -> authService.getAccessToken()
.flatMap(token -> post("/save", request,
token.getAccessToken(),
ctx)
.bodyToMono(ApplicationResponse.class))
.log());
});
}
答案 0 :(得分:2)
如果您确定将使用getEndpoint2(request1)获得助焊剂,在这种情况下,可以使用collectList():
return webclient.getEndpoint2(request1) // Flux<Response2>
.collectList() // Mono<List<Response2>>
.flatMap(list -> {
// ... should handle empty list if needed
finalRequest = createRequest(request1, list);
return webclient.getSomething(finalRequest); // Mono<Response1>
});
答案 1 :(得分:0)
我看到了一些有趣的事情。如果我从Controller类中进行协调,则按预期方式工作,而如果从Controller类中进行协调的流程中调用服务,则该服务似乎无法按预期方式工作。只是想知道我在想什么?还是这意味着工作?
这是工作代码:
@RestController
@RequestMapping("/applications")
@Slf4j
@RequiredArgsConstructor
public class ApplicationController {
private final ApplicationService applicationService;
private final ApplicationRequestMapper requestMapper;
private final FeesService feesService;
@PostMapping(value = "/save")
public Mono<Application> saveApplication(@RequestBody ApplicationRequest request) {
ApplicationRequest applicationRequest = requestMapper.apply(request);
return Mono.subscriberContext()
.flatMap(context -> feesService.calculateApplicationFees(applicationRequest)
.collectList())
.map(feeItems -> applicationRequest.getFeeItems().addAll(feeItems))
.flatMap(isRequestEnriched -> applicationService.saveApplication(applicationRequest)
.map(saveApplicationResponse -> {
Application application = new Application();
application.setLicenceId(saveApplicationResponse.getResponse().getLicenceNumber());
return application;
}))
.onErrorMap(throwable -> new ApplicationException(String.format(SAVE_ERROR_MESSAGE,
request.getLicenceId()),
throwable, true, false))
.log();
}
}
@Service
@Slf4j
@RequiredArgsConstructor
public class ApplicationService extends ClientService{
private final AuthenticationService authenticationService;
public Mono<SaveApplicationResponse> saveApplication(ApplicationRequest request) {
return Mono.subscriberContext()
.flatMap(context -> authenticationService.getAccessToken()
.flatMap(token -> post("/save",
request,
token.getAccessToken(),
context)
.bodyToMono(SaveApplicationResponse.class))
.log());
}
}
@Service
@Slf4j
@RequiredArgsConstructor
public class FeesService extends ClientService{
private final AuthenticationService authenticationService;
public Flux<FeeItem> calculateApplicationFees(ApplicationRequest request) {
return Mono.subscriberContext()
.flatMap(ctx -> authenticationService.getAccessToken()
.flatMap(token -> get("/fees", request, token.getAccessToken(), ctx)
.bodyToMono(FeeResponse.class))
.log())
.flatMapMany(rsp -> Flux.fromIterable(rsp.getFeeItems()));
}
}
如果我这样做是行不通的。.意思是,该请求永远不会充实:
@RestController
@RequestMapping("/applications")
@Slf4j
@RequiredArgsConstructor
public class ApplicationController {
private final ApplicationService applicationService;
private final ApplicationRequestMapper requestMapper;
@PostMapping(value = "/save")
public Mono<Application> saveApplication(@RequestBody ApplicationRequest request) {
return Mono.subscriberContext()
.flatMap(context -> applicationService.saveApplication(requestMapper.apply(request))
.map(saveApplicationResponse -> {
Application application = new Application();
application.setLicenceId(saveApplicationResponse.getResponse().getLicenceNumber());
return application;
}))
.onErrorMap(throwable -> new ApplicationException(String.format(SAVE_ERROR_MESSAGE,
request.getLicenceId()),
throwable, true, false))
.log();
}
}
@Service
@Slf4j
@RequiredArgsConstructor
public class ApplicationService extends ClientService{
private final AuthenticationService authenticationService;
private final FeesService feesService;
public Mono<SaveApplicationResponse> saveApplication(ApplicationRequest request) {
return Mono.subscriberContext()
.flatMap(context -> feesService.calculateApplicationFees(request)
.collectList())
.map(feeItems -> request.getFeeItems().addAll(feeItems))
.subscriberContext()
.flatMap(context -> authenticationService.getAccessToken()
.flatMap(token -> post("/save",
request,
token.getAccessToken(),
context)
.bodyToMono(SaveApplicationResponse.class))
.log());
}
}
@Service
@Slf4j
@RequiredArgsConstructor
public class FeesService extends ClientService{
private final AuthenticationService authenticationService;
public Flux<FeeItem> calculateApplicationFees(ApplicationRequest request) {
return Mono.subscriberContext()
.flatMap(ctx -> authenticationService.getAccessToken()
.flatMap(token -> get("/fees", request, token.getAccessToken(), ctx)
.bodyToMono(FeeResponse.class))
.log())
.flatMapMany(rsp -> Flux.fromIterable(rsp.getFeeItems()));
}
}
答案 2 :(得分:0)
您的问题来自第二个.subscriberContext()
。这是一个静态方法,会创建一个新的Mono
,这意味着从不执行代码,这就是request
对象不变的原因。
无论如何,您的代码很混乱。使它更简单。据我阅读您的代码,您根本不需要Flux
。 feesService.calculateApplicationFees(...)
应该返回Mono<List<FeeItem>>
。不必要的.log()
或Mono.subscriberContext()
太多。您甚至需要这里的上下文吗?