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

如何在Quarkus服务间传递异常详情至调用服务?

在Quarkus服务间传递异常信息的实现方案

服务端(抛出异常的服务)处理

要让异常信息能被客户端识别,首先得把自定义异常转换成带结构化信息的HTTP响应体,替代默认的空500响应:

  • 自定义业务异常类:封装错误码、错误信息等核心字段

    public class CustomServiceException extends RuntimeException {
        private final String errorCode;
        private final String errorMessage;
    
        public CustomServiceException(String errorCode, String errorMessage) {
            super(errorMessage);
            this.errorCode = errorCode;
            this.errorMessage = errorMessage;
        }
    
        // Getter方法
        public String getErrorCode() { return errorCode; }
        public String getErrorMessage() { return errorMessage; }
    }
    
  • 实现ExceptionMapper:将自定义异常映射为JSON格式的HTTP响应

    @Provider
    public class CustomExceptionMapper implements ExceptionMapper<CustomServiceException> {
    
        @Override
        public Response toResponse(CustomServiceException exception) {
            ErrorResponse errorResponse = new ErrorResponse(
                exception.getErrorCode(),
                exception.getErrorMessage()
            );
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                    .entity(errorResponse)
                    .type(MediaType.APPLICATION_JSON)
                    .build();
        }
    
        // 统一的错误响应体结构
        public static class ErrorResponse {
            private String errorCode;
            private String errorMessage;
    
            public ErrorResponse(String errorCode, String errorMessage) {
                this.errorCode = errorCode;
                this.errorMessage = errorMessage;
            }
    
            // Getter方法
            public String getErrorCode() { return errorCode; }
            public String getErrorMessage() { return errorMessage; }
        }
    }
    
  • 在业务逻辑中抛出异常:

    @GET
    @Path("/fetch-data")
    public String fetchData() {
        // 模拟业务异常场景
        throw new CustomServiceException("DATA_001", "请求的资源不存在");
    }
    

客户端(调用方服务)处理

通过Rest Client的异常映射器,解析服务端返回的错误响应体,转换成客户端可直接使用的异常:

  • 自定义客户端异常类:用于接收服务端传递的异常信息

    public class ClientServiceException extends RuntimeException {
        private final String errorCode;
        private final String errorMessage;
    
        public ClientServiceException(String errorCode, String errorMessage) {
            super(errorMessage);
            this.errorCode = errorCode;
            this.errorMessage = errorMessage;
        }
    
        // Getter方法
        public String getErrorCode() { return errorCode; }
        public String getErrorMessage() { return errorMessage; }
    }
    
  • 实现ClientExceptionMapper:解析服务端的错误响应,转换为客户端异常

    @Provider
    public class ClientExceptionMapper implements ClientExceptionMapper<Response> {
    
        @Override
        public RuntimeException toThrowable(Response response) {
            if (response.getStatus() == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
                try {
                    ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);
                    return new ClientServiceException(
                        errorResponse.getErrorCode(),
                        errorResponse.getErrorMessage()
                    );
                } catch (Exception e) {
                    return new RuntimeException("解析服务端异常失败", e);
                }
            }
            return new RuntimeException("服务调用失败,状态码:" + response.getStatus());
        }
    
        // 和服务端一致的错误响应体结构
        public static class ErrorResponse {
            private String errorCode;
            private String errorMessage;
    
            // Getter方法
            public String getErrorCode() { return errorCode; }
            public String getErrorMessage() { return errorMessage; }
        }
    }
    
  • 配置Rest Client并调用:

    @RegisterRestClient(baseUri = "http://your-server-host:8080")
    @RegisterProvider(ClientExceptionMapper.class)
    public interface DataServiceClient {
        @GET
        @Path("/fetch-data")
        String fetchData();
    }
    
    // 调用示例
    @Inject
    @RestClient
    DataServiceClient dataServiceClient;
    
    public void invokeService() {
        try {
            dataServiceClient.fetchData();
        } catch (ClientServiceException e) {
            // 这里可以获取到服务端传递的具体异常信息
            System.out.println("错误码:" + e.getErrorCode());
            System.out.println("错误信息:" + e.getErrorMessage());
        }
    }
    

关键注意事项

  • 服务端和客户端的ErrorResponse结构必须完全一致,否则会导致解析失败
  • 如果需要传递堆栈信息,可以在ErrorResponse中添加stackTrace字段,服务端抛出异常时捕获并序列化堆栈
  • 对于系统级异常(如NullPointerException),可以额外实现ExceptionMapper<Throwable>统一封装成标准错误响应

内容的提问来源于stack exchange,提问作者Rahul Malawadkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:33:25