You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring 5响应式HTTP响应异常处理及微服务场景技术咨询

处理WebFlux远程调用HTTP状态及全局异常捕获方案

我刚好在Spring WebFlux项目里踩过类似的坑,给你一步步拆解完整的解决方案:

1. 自定义异常类

首先得搞一个专属异常来封装远程服务返回的异常HTTP状态,方便后续全局捕获处理:

public class RemoteServiceException extends RuntimeException {
    private final HttpStatus statusCode;

    public RemoteServiceException(HttpStatus statusCode, String message) {
        super(message);
        this.statusCode = statusCode;
    }

    public HttpStatus getStatusCode() {
        return statusCode;
    }
}

2. 配置WebClient拦截HTTP响应

WebFlux里调用远程REST服务用WebClient,我们可以给它加个过滤器,统一拦截所有响应并检查状态码:

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .filter(ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
                    // 只要状态码是错误范畴(4xx、5xx),就抛出我们的自定义异常
                    if (clientResponse.statusCode().isError()) {
                        return clientResponse.bodyToMono(String.class)
                                .flatMap(errorBody -> Mono.error(
                                        new RemoteServiceException(
                                                clientResponse.statusCode(),
                                                "远程服务调用失败:状态码" + clientResponse.statusCode() + ",错误详情:" + errorBody
                                        )
                                ));
                    }
                    return Mono.just(clientResponse);
                }))
                .build();
    }
}

这里的逻辑很直白:拿到响应先看状态,要是异常就读取响应体的错误信息,封装成自定义异常抛出去。

3. 全局异常处理器(对标Spring 4的@ControllerAdvice)

WebFlux里对应的全局异常处理用@RestControllerAdvice,搭配@ExceptionHandler就能实现和Spring MVC完全一致的全局捕获效果:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RemoteServiceException.class)
    public ResponseEntity<ErrorResponse> handleRemoteServiceException(RemoteServiceException ex) {
        ErrorResponse errorResponse = new ErrorResponse(
                ex.getStatusCode().value(),
                ex.getMessage(),
                LocalDateTime.now()
        );
        return new ResponseEntity<>(errorResponse, ex.getStatusCode());
    }

    // 可以额外加其他异常的兜底处理,比如全局运行时异常
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
        ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                "服务器内部错误:" + ex.getMessage(),
                LocalDateTime.now()
        );
        return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    // 封装错误响应的DTO,按需补充getter/setter
    public static class ErrorResponse {
        private int status;
        private String message;
        private LocalDateTime timestamp;

        public ErrorResponse(int status, String message, LocalDateTime timestamp) {
            this.status = status;
            this.message = message;
            this.timestamp = timestamp;
        }

        // getter方法
        public int getStatus() { return status; }
        public String getMessage() { return message; }
        public LocalDateTime getTimestamp() { return timestamp; }
    }
}

这个处理器会自动捕获我们抛出的RemoteServiceException,然后返回结构化的错误响应,和你熟悉的Spring 4中@ControllerAdvice的效果一模一样。

4. 实际调用远程服务

现在你在业务代码里用配置好的WebClient调用远程服务时,只要对方返回异常状态码,就会自动触发异常抛出,然后被全局处理器捕获并返回统一响应:

@Service
public class RemoteCallService {

    private final WebClient webClient;

    public RemoteCallService(WebClient webClient) {
        this.webClient = webClient;
    }

    public Mono<User> getUserById(String userId) {
        return webClient.get()
                .uri("https://remote-service/api/users/{id}", userId)
                .retrieve()
                .bodyToMono(User.class);
    }
}

比如远程服务返回404时,WebClient的过滤器会立刻抛出RemoteServiceException,随后全局处理器会返回包含404状态码和错误信息的响应体。

这样一套流程走下来,就完美实现了你要的:统一处理远程调用的所有HTTP状态,异常状态抛异常,再通过全局处理器统一返回响应的需求。

内容的提问来源于stack exchange,提问作者Dina Bogdan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:40:23