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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:24:59