基于Kickstart GraphQL实现自定义异常响应格式
自定义Kickstart GraphQL错误响应格式
问题场景
使用Kickstart GraphQL库时,遇到两种错误场景需要统一转换为自定义格式:
- 输入参数超出Int范围时,框架返回默认验证错误
- Resolver中抛出
CustomGraphQLError自定义异常时
当前默认错误响应(超出Int限制示例)
{ "errors": [ { "message": "Validation error of type WrongType: argument 'inputLocals.localId' with value 'IntValue{value=7777800}' is not a valid 'Int' - Expected value to be in the Integer range but it was '7777800' @ 'getLocals'", "locations": [ { "line": 1, "column": 25 } ], "extensions": { "classification": "ValidationError" } } ], "data": null }
期望的自定义错误格式
{ "code": "400", "reason": "BAD_REQUEST", "message": "/localId 7777800 is not less or equal to 99999", "status": "", "referenceError": "" }
现有Resolver代码
@Override public OutputLocals getLocals(InputLocals inputLocals) throws CustomGraphQLError { int localId = inputLocals.localId(); if (localId > 99999) { throw new CustomGraphQLError("fields matching the JSON above"); } // 剩余业务代码 }
解决方案
1. 重构自定义异常类CustomGraphQLError
让异常携带字段和值信息,方便后续生成标准化错误消息:
public class CustomGraphQLError extends RuntimeException { private final String field; private final String value; public CustomGraphQLError(String field, String value) { super(String.format("/%s %s is not less or equal to 99999", field, value)); this.field = field; this.value = value; } public String getField() { return field; } public String getValue() { return value; } }
同时修改Resolver中抛出异常的逻辑:
if (localId > 99999) { throw new CustomGraphQLError("localId", String.valueOf(localId)); }
2. 实现自定义错误处理器
创建CustomGraphQLErrorHandler继承默认处理器,统一处理两类错误:
import graphql.ExceptionWhileDataFetching; import graphql.GraphQLError; import graphql.validation.ValidationError; import org.springframework.graphql.execution.DefaultGraphQLErrorHandler; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; @Component public class CustomGraphQLErrorHandler extends DefaultGraphQLErrorHandler { @Override public List<GraphQLError> processErrors(List<GraphQLError> errors) { return errors.stream() .map(this::convertToCustomFormat) .collect(Collectors.toList()); } private GraphQLError convertToCustomFormat(GraphQLError error) { // 处理Resolver抛出的自定义异常 if (error instanceof ExceptionWhileDataFetching) { Throwable cause = ((ExceptionWhileDataFetching) error).getException(); if (cause instanceof CustomGraphQLError) { return new CustomErrorResponse( "400", "BAD_REQUEST", cause.getMessage(), "", "" ); } } // 处理框架默认的参数验证错误 if (error instanceof ValidationError) { String msg = ((ValidationError) error).getMessage(); String field = extractField(msg); String value = extractValue(msg); String customMsg = String.format("/%s %s is not less or equal to 99999", field, value); return new CustomErrorResponse( "400", "BAD_REQUEST", customMsg, "", "" ); } // 其他错误保持默认处理 return error; } // 从默认错误消息中提取字段名 private String extractField(String message) { int start = message.indexOf("argument '") + 10; int end = message.indexOf("' with value"); String fullField = message.substring(start, end); return fullField.substring(fullField.lastIndexOf(".") + 1); } // 从默认错误消息中提取参数值 private String extractValue(String message) { int start = message.indexOf("value '") + 7; int end = message.indexOf("}' is not a valid"); return message.substring(start, end); } }
3. 定义自定义错误响应类
实现GraphQLError接口,确保输出格式完全符合预期:
import graphql.GraphQLError; import graphql.language.SourceLocation; import java.util.List; import java.util.Map; public class CustomErrorResponse implements GraphQLError { private final String code; private final String reason; private final String message; private final String status; private final String referenceError; public CustomErrorResponse(String code, String reason, String message, String status, String referenceError) { this.code = code; this.reason = reason; this.message = message; this.status = status; this.referenceError = referenceError; } @Override public String getMessage() { return message; } @Override public List<SourceLocation> getLocations() { return null; } @Override public Map<String, Object> getExtensions() { return Map.of(); } // 重写该方法,直接返回自定义格式的Map @Override public Map<String, Object> toSpecification() { return Map.of( "code", code, "reason", reason, "message", message, "status", status, "referenceError", referenceError ); } }
4. 配置处理器(Spring环境)
如果是Spring Boot项目,CustomGraphQLErrorHandler上的@Component注解会让Spring自动扫描并注册;如果是手动配置,可添加如下配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.graphql.execution.GraphQLErrorHandler; @Configuration public class GraphQLConfig { @Bean public GraphQLErrorHandler graphQLErrorHandler() { return new CustomGraphQLErrorHandler(); } }
内容的提问来源于stack exchange,提问作者cdelrey
相关产品推荐
相关产品推荐

