Spring Reactive Web - 异常总是包含在 500 中
Posted
技术标签:
【中文标题】Spring Reactive Web - 异常总是包含在 500 中【英文标题】:Spring Reactive Web - Exceptions are always wrapped in 500 【发布时间】:2020-12-18 10:43:15 【问题描述】:对于一个非常简单的项目,错误处理不清楚。
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 调用和处理不同类型响应的示例。
【问题讨论】:
为什么需要它来处理 badRequest。默认情况下,在 Spring Boot 中,非映射 url 返回 404 错误。除了你的 500 错误是由于你的 /api/v1/integration/notfound 没有过时。从 WebClient 调用时,它应该类似于 localhost:8080/api/v1/integration/notfound。但这一次会有循环。你的目的是什么? 从错误中可以看出,404来自httpbin.org/status/404。我正在尝试处理来自外部客户端的 404。如果我们的端点调用另一个端点,它应该能够处理任何状态码。 /ok 端点工作正常。 【参考方案1】:只需添加 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()) );
【讨论】:
我完全误解了错误处理的工作原理,这非常有效!谢谢!以上是关于Spring Reactive Web - 异常总是包含在 500 中的主要内容,如果未能解决你的问题,请参考以下文章
Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.
Spring Reactive Web 更新方法创建新记录而不是更新现有记录
Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency(代码