java - Spring Reactive Web - 异常总是包含在 500 中

标签 java spring spring-boot spring-webflux reactive

对于一个非常简单的项目,错误处理不清楚。

public class WebfluxApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebfluxApplication.class, args);
    }
}
public class EndpointRouter
{

@Bean
public WebClient webClient() {
    return WebClient.builder().build();
}

@Bean
public RouterFunction<ServerResponse> goodRoute(Handler handler, ConfigProperties configProperties) {
    log.info(configProperties.toString());
    return
            RouterFunctions.route(RequestPredicates.GET("/api/v1/integration/ok"),
                    handler::goodEndpoint)
    .and(
            RouterFunctions.route(RequestPredicates.GET("/api/v1/integration/notfound") {
                    handler::badEndpoint));
}
public Mono<ServerResponse> goodEndpoint(ServerRequest r) {
    return ServerResponse.ok().build();
}

public Mono<ServerResponse> badEndpoint(ServerRequest r) {
    var result = service.badEndpoint();
    return ServerResponse
            .ok()
            .body(result, String.class);
}
public class Service
{
private final WebClient webClient;
private final ConfigProperties configProperties;

public Service(WebClient webClient, ConfigProperties configurationProperties) {
    this.webClient = webClient;
    this.configProperties = configurationProperties;
}

public Mono<String> badEndpoint() {
    return webClient
            .get()
            .uri(configProperties.getNotfound())
            .retrieve()
            .onStatus(HttpStatus::is4xxClientError, clientResponse -> {
                if(clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)){
                    return Mono.error(new HttpClientErrorException(HttpStatus.NOT_FOUND,
                            "Entity not found."));
                } else {
                    return Mono.error(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
                }
            })
            .bodyToMono(String.class);
}

通过阅读文档,我不需要为整个项目设置全局错误处理程序,我应该能够处理 404,并将 404 返回给原始调用者。

这是输出

   2020-08-29 16:52:46.301 ERROR 25020 --- [ctor-http-nio-4] a.w.r.e.AbstractErrorWebExceptionHandler : [b339763e-1]  500 Server Error for HTTP GET "/api/v1/integration/notfound"

org.springframework.web.client.HttpClientErrorException: 404 Entity not found.
    at com.stevenpg.restperformance.webflux.Service.lambda$badEndpoint$0(Service.java:30) ~[main/:na]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ 404 from GET https://httpbin.org/status/404 [DefaultWebClient]
    |_ checkpoint ⇢ Handler com.stevenpg.restperformance.webflux.EndpointRouter$$Lambda$445/0x00000008003ae040@7799b58 [DispatcherHandler]
    |_ checkpoint ⇢ HTTP GET "/api/v1/integration/notfound" [ExceptionHandlingWebHandler]

我也尝试过在服务中的 Mono 上使用 onErrorResume,但它永远无法正常工作,并且需要返回 Mono 而不是 Mono。

文档和 Stack Overflow 没有太多/任何在 RouterFunction 内进行 WebClient 调用并处理不同类型响应的示例。

最佳答案

只需添加 onErrorResume 即可解决您的问题。否则错误将在 AbstractErrorWebExceptionHandler 中处理。

 return webClient
        .get()
        .uri(configProperties.getNotfound())
        .retrieve()
        .onStatus(HttpStatus::is4xxClientError, clientResponse -> {
            if(clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)){
                return Mono.error(new HttpClientErrorException(HttpStatus.NOT_FOUND,
                        "Entity not found."));
            } else {
                return Mono.error(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
            }
        })
        .bodyToMono(String.class)
        .onErrorResume( e -> Mono.just(e.getMessage()) );

关于java - Spring Reactive Web - 异常总是包含在 500 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63651723/

相关文章:

java - Spring Boot中一个类的多个配置树

java - Spring Boot 应用程序端点返回 403

java - 验证服务器到服务器的通信

java - 正确设置mysql排序规则

java - AS3 到 Java( boolean 值? int :int)

java - 在字符串中放入逗号

java - MappingException : Invalid path reference club. 名称!关联只能直接指向或通过其 id 属性指向

java - Spring MimeMessageHelper 附件文件名编码

java - Mockito 不起作用 MockitoSessionLogger DefFoundError

java - System.out.println() 不会抛出异常,但 System.in.read() 会抛出异常,为什么?