我正在使用 GraphQL-SPQR 和 Spring Boot 运行 GraphQL API。
目前,我正在抛出RuntimeException
s来返回 GraphQL 错误。我有一个实现DataFetcherExceptionHandler
的customExceptionHandler
,它以正确的格式返回错误,如下所示:
class CustomExceptionHandler : DataFetcherExceptionHandler {
override fun onException(handlerParameters: DataFetcherExceptionHandlerParameters?): DataFetcherExceptionHandlerResult {
// get exception
var exception = handlerParameters?.exception
val locations = listOf(handlerParameters?.sourceLocation)
val path = listOf(handlerParameters?.path?.segmentName)
// create a GraphQLError from your exception
if (exception !is GraphQLError) {
exception = CustomGraphQLError(exception?.localizedMessage, locations, path)
}
// cast to GraphQLError
exception as CustomGraphQLError
exception.locations = locations
exception.path = path
val errors = listOf<GraphQLError>(exception)
return DataFetcherExceptionHandlerResult.Builder().errors(errors).build()
}
}
我按如下方式使用CustomExceptionHandler
(在我的主应用程序类中(:
@Bean
fun graphQL(schema: GraphQLSchema): GraphQL {
return GraphQL.newGraphQL(schema)
.queryExecutionStrategy(AsyncExecutionStrategy(CustomExceptionHandler()))
.mutationExecutionStrategy(AsyncSerialExecutionStrategy(CustomExceptionHandler()))
.build()
}
我想为与异常对应的 UUID 设置一个标头变量,以便进行日志记录。我该怎么做?
更好的是,是否可以创建一个 Spring Bean,将所有查询和突变的 UUID 放在标头中?
谢谢!
当你使用Spring Boot时,有两个选项:
- 您正在使用 Spring Boot GraphQL SPQR 启动器(它带来了自己的控制器来处理所有 GraphQL 请求(
- 你正在使用普通的 GraphQL-spqr,并且有自己的控制器来处理 GraphQL 请求
无论如何,您都有以下几种选择:
使 CustomExceptionHandler 成为 Spring Bean 并自动连线 HttpServletResponse
这可能是最简单的方法 - 它在任何情况下都可能有效:您可以简单地将CustomExceptionHandler设置为Spring bean并让它自动连接HttpServletRequest - 在处理程序方法中,您可以将其设置为您想要的任何内容。这里有一些 Java 中的虚拟代码(对不起,我对 Kotlin 不够精通(:
@Component
class CustomExceptionHandler implements DataFetcherExceptionHandler {
private final HttpServletResponse response;
public CustomExceptionHandler(HttpServletResponse response) {
this.response = response;
}
@Override
public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) {
response.setHeader("X-Request-ID", UUID.randomUUID().toString());
// ... your actual error handling code
}
}
这是可行的,因为 spring 会意识到 HttpServletRequest 对于每个请求都是不同的。因此,它会将一个动态代理注入到您的错误处理程序中,该代理将指向每个请求的实际 HttpServletResponse 实例。
我认为,这不是最优雅的方式,但它肯定会解决你的问题。
对于 GraphQL-SPQR 弹簧启动器
有一个默认控制器实现,用于使用此启动器的项目。该控制器将处理您收到的每个 graphql 请求。你可以通过实现你自己的GraphQLExecutor并使其成为春豆来自定义它。该执行器负责调用 GraphQL 引擎,传入参数并输出响应。下面是你可能希望基于其工作的默认实现。
与前面的解决方案类似,您可以在该类中自动连接 HttpServletResponse 并设置 HTTP Response 标头。
该解决方案将允许您决定是要在所有情况下设置请求 ID,还是仅在特定错误情况下设置请求 ID。(graphql.execute
返回一个对象,您可以从中获取错误是否以及存在哪些错误的信息(
在没有弹簧启动器的情况下使用 GraphQL-SPQR 时
找到你的 GraphQL 控制器,向该方法添加一个 HttpServletRequest 类型的参数 - 然后根据需要向其添加标头(请参阅上一节中一些更具体的建议(