如何处理网络客户端抛出的异常?

时间:2018-10-15 17:18:48

标签: spring-boot spring-webflux

无论从被调用的api返回的错误状态代码如何,我都试图弄清楚如何从webclient记录异常。

我已经看到以下实现:

.onStatus(status -> status.value() != HttpStatus.OK.value(),
            rs -> rs.bodyToMono(String.class).map(body -> new IOException(String.format(
                "Response HTTP code is different from 200: %s, body: '%s'", rs.statusCode(), body))))

我看到的另一个示例使用过滤器。我猜这个过滤器也可以用于记录错误,除了本示例中的请求之外:

public MyClient(WebClient.Builder webClientBuilder) {
    webClient = webClientBuilder // you can also just use WebClient.builder()
            .baseUrl("https://httpbin.org")
            .filter(logRequest()) // here is the magic
            .build();
}

但是我们是否真的没有针对此问题的专用异常处理程序?

1 个答案:

答案 0 :(得分:0)

找到了。
如果状态码是4xx(客户端错误)或5xx(服务器错误),则bodyToMono会引发WebClientException。

服务的完整实现:​​

@Service
public class FacebookService {
    private static final Logger LOG = LoggerFactory.getLogger(FacebookService.class);
    private static final String URL_DEBUG = "https://graph.facebook.com/debug_token";
    private WebClient webClient;

    public FacebookService() {
        webClient = WebClient.builder()
                .filter(logRequest())
                .build();
    }

    public Mono<DebugTokenResponse> verifyFbAccessToken(String fbAccessToken, String fbAppToken) {
        LOG.info("verifyFacebookToken for " + String.format("fbAccessToken: %s and fbAppToken: %s", fbAccessToken, fbAppToken));
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(URL_DEBUG)
                .queryParam("input_token", fbAccessToken)
                .queryParam("access_token", fbAppToken);
        return this.webClient.get()
                .uri(builder.toUriString())
                .retrieve()
                .bodyToMono(DebugTokenResponse.class);
    }

    private static ExchangeFilterFunction logRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            LOG.info("Request: {} {}", clientRequest.method(), clientRequest.url());
            clientRequest.headers().forEach((name, values) -> values.forEach(value -> LOG.info("{}={}", name, value)));
            return Mono.just(clientRequest);
        });
    }

    @ExceptionHandler(WebClientResponseException.class)
    public ResponseEntity<String> handleWebClientResponseException(WebClientResponseException ex) {
        LOG.error("Error from WebClient - Status {}, Body {}", ex.getRawStatusCode(), ex.getResponseBodyAsString(), ex);
        return ResponseEntity.status(ex.getRawStatusCode()).body(ex.getResponseBodyAsString());
    }
}