如何在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
相关产品推荐
相关产品推荐

