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

如何在Micronaut的@Body注解中捕获错误并抛出结构化异常

在Micronaut中捕获并格式化@Body绑定失败的异常

针对你遇到的问题——当@Body无法创建请求对象时无法捕获异常并返回标准化格式,分两种场景给出解决方案:

服务端场景:捕获请求体解析失败的异常

当客户端发送的请求体无法被反序列化为控制器方法的@Body参数时,Micronaut会抛出HttpMessageConversionException,这个异常不会被控制器内的try-catch或普通@Error注解捕获,因为请求还未进入控制器逻辑。你需要实现全局异常处理器来处理它:

import io.micronaut.context.annotation.Requires;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.server.exceptions.ExceptionHandler;
import jakarta.inject.Singleton;

@Produces
@Singleton
@Requires(classes = {HttpMessageConversionException.class, ExceptionHandler.class})
public class RequestBodyParseExceptionHandler implements ExceptionHandler<HttpMessageConversionException, HttpResponse<StandardizedError>> {

    @Override
    public HttpResponse<StandardizedError> handle(HttpRequest request, HttpMessageConversionException exception) {
        StandardizedError error = new StandardizedError();
        error.setCode("REQUEST_BODY_PARSE_FAILED");
        error.setMessage("请求体格式无效,无法解析为目标对象");
        error.setDetails(exception.getCause().getMessage());

        return HttpResponse.badRequest().body(error);
    }

    // 自定义标准化异常响应类
    public static class StandardizedError {
        private String code;
        private String message;
        private String details;

        // 此处添加getter和setter方法
    }
}

这个处理器会全局捕获所有请求体解析失败的异常,返回你定义的标准化响应格式。

客户端场景:捕获HttpClientResponseException

如果你的应用作为客户端调用外部服务,因请求体序列化失败或对方返回错误导致抛出HttpClientResponseException,可以通过两种方式处理:

方式1:局部try-catch捕获

在客户端调用代码中直接捕获异常并格式化:

try {
    HttpResponse<YourResponse> response = httpClient.toBlocking().exchange(
        HttpRequest.POST("/external/api", yourRequestBody),
        YourResponse.class
    );
} catch (HttpClientResponseException e) {
    StandardizedError error = new StandardizedError();
    error.setCode("CLIENT_REQUEST_ERROR");
    error.setMessage("调用外部服务失败");
    error.setDetails(e.getResponse().getBody(String.class).orElse("无详细错误信息"));
    // 此处处理或返回标准化异常
}

方式2:全局ErrorDecoder处理

实现全局的ErrorDecoder来统一解析客户端异常:

import io.micronaut.http.HttpResponse;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.codec.ErrorDecoder;
import jakarta.inject.Singleton;

@Singleton
public class CustomClientErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String url, HttpResponse<?> response) {
        StandardizedError error = response.getBody(StandardizedError.class).orElse(null);
        if (error != null) {
            return new CustomClientException(error);
        }
        return new HttpClientResponseException("客户端请求失败", response);
    }

    // 自定义携带标准化错误的异常类
    public static class CustomClientException extends RuntimeException {
        private final StandardizedError error;

        public CustomClientException(StandardizedError error) {
            super(error.getMessage());
            this.error = error;
        }

        public StandardizedError getError() {
            return error;
        }
    }
}

之后你可以在调用处捕获CustomClientException,直接获取标准化的错误信息。


内容的提问来源于stack exchange,提问作者Nick Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 14:03:07