SPQR(GraphQL)异常处理配置无效问题求助
GraphQL SPQR 异常处理配置问题
问题场景
配置SPQR(GraphQL)异常处理时,Resolver主动抛出NullPointerException后,接口响应仅返回{"books": null},无法获取异常信息。相关代码如下:
1. GraphQL控制器代码
@Autowired public GraphqlController(BookResolver bookResolver) { GraphQLSchema schema = new GraphQLSchemaGenerator() .withBasePackages("com.graphql.learn") .withOperationsFromSingleton(bookResolver) .generate(); this.graphQL = new GraphQL.Builder(schema) .queryExecutionStrategy(new AsyncExecutionStrategy(new CustomExceptionHandler())) .mutationExecutionStrategy(new AsyncExecutionStrategy(new CustomExceptionHandler())) .build(); } @PostMapping(value = "/graphql") public Map<String, Object> execute(@RequestBody Map<String, String> request, HttpServletRequest raw) throws GraphQLException { ExecutionResult result = graphQL.execute(request.get("query")); return result.getData(); }
2. Resolver代码
@GraphQLQuery public List<Book> books(){ if(true){ throw new NullPointerException("Null pointer exception"); } return bookService.getAll(); }
3. 自定义异常处理器代码
@Component public class CustomExceptionHandler implements DataFetcherExceptionHandler { private DataFetcherExceptionHandlerResult onExceptionHandler(DataFetcherExceptionHandlerParameters handlerParameters) { Throwable exception = handlerParameters.getException(); GraphQLError error = GraphqlErrorBuilder .newError() .message(exception.getMessage()) .build(); return DataFetcherExceptionHandlerResult .newResult() .error(error) .build(); } @Override public CompletableFuture<DataFetcherExceptionHandlerResult> handleException(DataFetcherExceptionHandlerParameters handlerParameters) { DataFetcherExceptionHandlerResult result = onExceptionHandler(handlerParameters); return CompletableFuture.completedFuture(result); } }
问题原因
核心问题在于控制器仅返回ExecutionResult中的data部分,未将处理后的errors信息包含到响应中;同时当前异常处理器未关联错误的位置、路径信息,导致错误维度不完整。
解决方案
1. 修改控制器返回逻辑
调整execute方法,将data和errors统一封装到响应体中:
@PostMapping(value = "/graphql") public Map<String, Object> execute(@RequestBody Map<String, String> request, HttpServletRequest raw) { ExecutionResult result = graphQL.execute(request.get("query")); Map<String, Object> response = new HashMap<>(); response.put("data", result.getData()); if (!result.getErrors().isEmpty()) { response.put("errors", result.getErrors()); } return response; }
2. 完善异常处理器的错误信息
构建GraphQLError时添加路径、位置信息,让错误定位更清晰:
private DataFetcherExceptionHandlerResult onExceptionHandler(DataFetcherExceptionHandlerParameters handlerParameters) { Throwable exception = handlerParameters.getException(); SourceLocation sourceLocation = handlerParameters.getSourceLocation(); List<Path> path = handlerParameters.getPath(); GraphQLError error = GraphqlErrorBuilder.newError() .message(exception.getMessage()) .path(path) .location(sourceLocation) .build(); return DataFetcherExceptionHandlerResult.newResult() .error(error) .build(); }
3. (可选)规范异常类型
定义自定义业务异常,区分业务异常与系统异常的处理逻辑:
// 自定义业务异常类 public class GraphQLBusinessException extends RuntimeException { public GraphQLBusinessException(String message) { super(message); } } // 修改Resolver抛出自定义异常 @GraphQLQuery public List<Book> books(){ if(true){ throw new GraphQLBusinessException("获取图书列表失败"); } return bookService.getAll(); } // 异常处理器中区分处理 private DataFetcherExceptionHandlerResult onExceptionHandler(DataFetcherExceptionHandlerParameters handlerParameters) { Throwable exception = handlerParameters.getException(); SourceLocation sourceLocation = handlerParameters.getSourceLocation(); List<Path> path = handlerParameters.getPath(); GraphQLError error; if (exception instanceof GraphQLBusinessException) { error = GraphqlErrorBuilder.newError() .message(exception.getMessage()) .path(path) .location(sourceLocation) .build(); } else { // 系统异常返回通用提示 error = GraphqlErrorBuilder.newError() .message("服务器内部错误") .path(path) .location(sourceLocation) .build(); } return DataFetcherExceptionHandlerResult.newResult() .error(error) .build(); }
验证效果
执行查询:
query{ books{ id, title } }
响应将包含完整错误信息,示例如下:
{ "data": {"books": null}, "errors": [ { "message": "Null pointer exception", "locations": [{"line": 2, "column": 5}], "path": ["books"] } ] }
内容的提问来源于stack exchange,提问作者hardkraja20
相关产品推荐
相关产品推荐

