Spring WebClient调用GraphQL服务时如何在HTTP 200状态下获取错误响应体
解决方案
方案1:通过通用GraphQL响应包装类处理(推荐)
核心思路:先定义符合GraphQL响应规范的通用包装实体,先将响应解析为该包装类,判断errors字段是否存在且非空,存在则处理错误,否则提取data字段转换为目标类型。
首先定义相关实体类:
// GraphQL错误信息实体 @Data public class GraphQLError { private String message; private List<Map<String, Integer>> locations; private Map<String, Object> extensions; }
// 通用GraphQL响应包装类 @Data public class GraphQLResponse<T> { private List<GraphQLError> errors; private T data; }
改造后的WebClient通用调用方法:
public <T> Mono<T> callGraphQLService(Object graphQLQuery, Class<T> classType) { // 构造带泛型的ParameterizedTypeReference,用于解析通用响应包装类 ParameterizedTypeReference<GraphQLResponse<T>> responseType = new ParameterizedTypeReference<GraphQLResponse<T>>() {}; return webClient() .post() .bodyValue(graphQLQuery) .retrieve() .bodyToMono(responseType) .flatMap(response -> { // 判断是否存在错误 if (response.getErrors() != null && !response.getErrors().isEmpty()) { // 此处可自定义异常,把errors信息带入,方便上层处理 return Mono.error(new GraphQLServiceException(response.getErrors())); } // 无错误直接返回业务数据 return Mono.just(response.getData()); }); }
方案2:通过JsonNode动态判断(无需额外定义实体)
如果不想新增GraphQL相关实体类,可以先将响应解析为JsonNode,动态判断errors节点是否存在:
public <T> Mono<T> callGraphQLService(Object graphQLQuery, Class<T> classType) { ObjectMapper objectMapper = new ObjectMapper(); return webClient() .post() .bodyValue(graphQLQuery) .retrieve() .bodyToMono(JsonNode.class) .flatMap(jsonNode -> { // 判断是否存在errors节点且非空 if (jsonNode.has("errors") && !jsonNode.get("errors").isEmpty()) { // 提取错误信息抛出自定义异常 String errorMsg = jsonNode.get("errors").get(0).get("message").asText(); return Mono.error(new RuntimeException("GraphQL调用错误:" + errorMsg)); } // 将data节点转换为目标类型 T data = objectMapper.convertValue(jsonNode.get("data"), classType); return Mono.just(data); }); }
两种方案都不需要依赖HTTP状态码,完全基于响应体内容做错误判断,完美适配GraphQL接口200状态码返回错误的场景。方案1类型更安全,适合有大量GraphQL调用的项目;方案2更轻量,适合调用频次低的场景。
内容的提问来源于stack exchange,提问作者Trond
相关产品推荐
相关产品推荐

