我正在尝试使用Spring Web Flux实现此代码:
public Mono<AuthorizeResponse> executeAndReceiveAuthorize(AuthorizeRequest transaction) {
Mono<AuthorizeRequest> transactionMono = Mono.just(transaction);
return client.post().uri(checkTrailingSlash(gatewayUrl) + token)
.......
.exchange()
.flatMap(clientResponse -> {
if (clientResponse.statusCode().is4xxClientError()) {
clientResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
return clientResponse.bodyToMono(AuthorizeResponse.class);
}
if (clientResponse.statusCode().is5xxServerError()) {
clientResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
return clientResponse.bodyToMono(AuthorizeResponse.class);
}
else
return clientResponse.bodyToMono(AuthorizeResponse.class);
});
}
//请求
public TransactionResponseFactory transactionProcess(AuthorizeRequestFactory tf) throws Exception {
......
TransactionResponseFactory response = null;
try {
RestClient client = RestClientBuilder.builder()
.gatewayUrl(URL)
.token(contract.getTerminal_token())
.build();
Mono<AuthorizeResponse> result = client.executeAndReceiveAuthorize(request);
result.doOnSuccess(e -> {
response = parseRawSuccessResponse(result.block());
}).doOnError(e -> {
response = parseRawFailedResponse(result.block());
throw new RuntimeException(e);
})
.block();
} catch (JAXBException e) {
e.printStackTrace();
}
return response;
}
private TransactionResponseFactory parseRawSuccessResponse(AuthorizeResponse response) {
............
}
private TransactionResponseFactory parseRawFailedResponse(AuthorizeResponse response) {
..........
}
如您所见,我想根据返回的状态码来解析响应。
但是我收到错误消息Local variable response defined in an enclosing scope must be final or effectively final
,因为我有不同的返回值,您能否指导我如何基于客户端响应代码调用两种方法parseRawSuccessResponse
和parseRawFailedResponse
?
编辑1:
我尝试过:
Mono<AuthorizeRequest> transactionMono = Mono.just(transaction);
return client.post().uri(checkTrailingSlash(gatewayUrl) + token)
.body(transactionMono, AuthorizeRequest.class)
.exchange()
.flatMap(clientResponse -> {
if (clientResponse.statusCode().is4xxClientError()) {
// We can handle errors by returning a Mono.error so that the event
// chain can trigger on doOnError later in the chain
return Mono.error(RuntimeException::new);
}
return clientResponse.bodyToMono(AuthorizeResponse.class);
});
//解析响应:
result.map(fooBar -> {
return parseRawSuccessResponse(fooBar);
}).doOnError(throwable -> {
// return parseRawFailedResponse(throwable);
}).block();
答案 0 :(得分:0)
您的代码中发生了几件奇怪的事情。
我将发布一个示例,说明如何使用WebClient进行错误处理。
final Mono<FooBar> fooBarMono = WebClient.create()
.get()
.exchange()
.flatMap(clientResponse -> {
if (clientResponse.statusCode().is4xxClientError()) {
// We can handle errors by returning a Mono.error so that the event
// chain can trigger on doOnError later in the chain
return Mono.error(RuntimeException::new);
}
return clientResponse.bodyToMono(FooBar.class);
});
return fooBarMono.map(fooBar -> {
return doSomethingWith(fooBar);
}).doOnError(throwable -> {
//Get our exception log something or whatever
}).block();
如果您的应用程序是纯Webflux客户端(您正在向客户端返回Mono
或Flux
),则不应在应用程序中调用block。
代码中有些奇怪的东西
clientResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
摘自Spring文档:
使用exchange()时,必须始终使用任何正文或 ClientResponse的toEntity方法,以确保释放资源 并避免HTTP连接池的潜在问题。您可以 如果没有响应内容,请使用bodyToMono(Void.class)。 但是,如果响应中确实包含内容,则连接已关闭 并且不会放回泳池中。
因此将导致泄漏。整个行应完全删除。
这也很奇怪。
result.doOnSuccess(e -> { // <- e is your value and you are not using it
response = parseRawSuccessResponse(result.block()); // <- instead you are blocking on the same mono you are in?
}
除非最终声明,否则您不能在(响应)之外声明某些内容并在lambda范围内使用它。而且您不能阻止正在发出信号的同一件事。那是因为你不能在lambda中改变状态。
// Declaring something outside can't later then be reassigned inside
// a lambda, the compiler will complain.
String value = "Hello ";
final Mono<String> world = Mono.just("World").doOnSuccess(w -> {
value = w;
});
那么我们如何更改值?
您必须使用map
或flatmap
String value = "Hello ";
String world = Mono.just("World").map(w -> value + w).block();
这也很奇怪。
.doOnError(e -> {
response = parseRawFailedResponse(result.block());
throw new RuntimeException(e);
}).block()
在这里您做同样的事情,您想要解析某些东西并分配它(编译器不允许),然后在引发异常后立即进行分配。如果要抛出异常,为什么要解析它?
所以您发生了一些奇怪的事情。