如何用Spring Boot RestTemplate调用GraphQL API?解决Bad Request报错
使用Spring Boot RestTemplate调用GraphQL接口报Bad Request的解决方法
问题概述
在Spring Boot应用中通过RestTemplate发送包含查询语句和变量的POST请求到GraphQL接口时,持续收到错误响应:{"errors":[{"message":"Bad request"}]},但相同逻辑用Python的requests库调用可正常获取结果。
问题排查与解决步骤
1. 对齐变量结构与查询字段
对比你的请求内容和Python代码,发现核心差异点,需先修正为与Python版本一致的正确结构:
- 将
sorting对象的by字段改为field,并补充direction字段(示例值为DESC) - 将
products对象的available字段改为primaryOnly - 将查询语句中的
Date字段改为releasedDt
2. 正确配置RestTemplate
确保RestTemplate具备正确的JSON序列化能力,添加Jackson消息转换器:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .setSerializationInclusion(JsonInclude.Include.NON_NULL)); restTemplate.getMessageConverters().add(0, converter); return restTemplate; } }
3. 构造请求并发送
方法1:使用DTO封装请求(推荐)
先定义GraphQL请求DTO类:
public class GraphQLRequest { private String query; private Map<String, Object> variables; public GraphQLRequest(String query, Map<String, Object> variables) { this.query = query; this.variables = variables; } // 自动生成getter、setter方法 }
然后编写调用逻辑:
@Autowired private RestTemplate restTemplate; public void invokeGraphQLApi() { String apiUri = "你的GraphQL接口地址"; // 构建与Python一致的查询语句 String query = """ query ($filter: SearchFilter!, $limit: Int!, $sorting: SearchSorting!) { search (filter: $filter, limit: $limit, sorting: $sorting) { cursor totalCount documents { id title products { name primaryCode } count releasedDt type { ids } } } }"""; // 构建正确的变量结构 Map<String, Object> filter = new HashMap<>(); Map<String, Object> date = new HashMap<>(); date.put("dt", "2023-01-01"); filter.put("date", date); Map<String, Object> types = new HashMap<>(); types.put("ids", List.of("1")); filter.put("types", types); Map<String, Object> products = new HashMap<>(); products.put("include", List.of("aaa")); products.put("primaryOnly", true); filter.put("products", products); Map<String, Object> category = new HashMap<>(); category.put("ids", List.of("A12")); filter.put("category", category); Map<String, Object> sorting = new HashMap<>(); sorting.put("field", "DATE"); sorting.put("direction", "DESC"); Map<String, Object> variables = new HashMap<>(); variables.put("filter", filter); variables.put("sorting", sorting); variables.put("limit", 500); // 设置请求头(与Python的getHeaders()保持一致,比如认证信息) HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", "Bearer 你的认证令牌"); // 按需添加 HttpEntity<GraphQLRequest> requestEntity = new HttpEntity<>(new GraphQLRequest(query, variables), headers); ResponseEntity<String> response = restTemplate.postForEntity(apiUri, requestEntity, String.class); // 处理响应结果 System.out.println(response.getBody()); }
方法2:直接用Map构造请求体
若不想创建DTO类,可直接用Map封装请求内容:
Map<String, Object> requestBody = new HashMap<>(); requestBody.put("query", query); requestBody.put("variables", variables); HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers); ResponseEntity<String> response = restTemplate.postForEntity(apiUri, requestEntity, String.class);
关键注意事项
- 必须设置请求头
Content-Type: application/json,这是GraphQL POST请求的标准要求 - 变量的字段名、类型需严格匹配GraphQL Schema定义,避免字段名错误
- 使用Java 15+的多行字符串语法(
""")可避免查询语句的转义问题,降低语法错误概率
内容的提问来源于stack exchange,提问作者Babu
相关产品推荐
相关产品推荐

