使用RestTemplate调用GraphQL接口时出现400 Bad Request错误
SpringBoot中RestTemplate调用GraphQL API报400 Bad Request的解决方法
在SpringBoot中使用RestTemplate调用公开GraphQL API(https://countries.trevorblades.com/graphql)时,多次出现*HttpClientErrorException$BadRequest: 400 Bad Request*错误,以下是问题场景及解决方案:
问题场景1:Content-Type设为APPLICATION_GRAPHQL
代码实现
public class GetRespPayLoad { private final String url = "https://countries.trevorblades.com/graphql"; public void getPayload(){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_GRAPHQL); String query = "{\n" + " country(code: \"BR\") {\n" + " name\n" + " native\n" + " capital\n" + " emoji\n" + " currency\n" + " languages {\n" + " code\n" + " name\n" + " }\n" + " }"; ResponseEntity<String> response = restTemplate.postForEntity(url, new HttpEntity<>(query, headers), String.class); System.out.println(response); } }
错误信息
Caused by: org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: "POST body missing, invalid Content-Type, or JSON object has no keys."
问题场景2:Content-Type设为APPLICATION_JSON
代码实现
public class GetRespPayLoad { private final String url = "https://countries.trevorblades.com/graphql"; public void getPayload(){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); String query = "query Query {\n" + " country(code: \"BR\") {\n" + " name\n" + " native\n" + " capital\n" + " emoji\n" + " currency\n" + " languages {\n" + " code\n" + " name\n" + " }\n" + " }\n" + "}"; ResponseEntity<String> response = restTemplate.postForEntity(url, new HttpEntity<>(query, headers), String.class); System.out.println(response); } }
错误信息
Caused by: org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: "Error
Bad Request"
解决方案
方案1:使用APPLICATION_JSON格式(推荐)
GraphQL的application/json请求要求体是包含query字段的JSON对象,而非直接传入查询字符串。可以通过Map构建请求体避免手动转义:
public class GetRespPayLoad { private final String url = "https://countries.trevorblades.com/graphql"; public void getPayload(){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); Map<String, String> requestBody = new HashMap<>(); requestBody.put("query", "query { country(code: \"BR\") { name native capital emoji currency languages { code name } } }"); ResponseEntity<String> response = restTemplate.postForEntity(url, new HttpEntity<>(requestBody, headers), String.class); System.out.println(response.getBody()); } }
方案2:使用APPLICATION_GRAPHQL格式
RestTemplate默认未注册application/graphql的消息转换器,需手动添加后再发送请求:
public class GetRespPayLoad { private final String url = "https://countries.trevorblades.com/graphql"; public void getPayload(){ RestTemplate restTemplate = new RestTemplate(); // 注册支持application/graphql的消息转换器 restTemplate.getMessageConverters().add(new StringHttpMessageConverter(MediaType.APPLICATION_GRAPHQL)); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_GRAPHQL); String query = "{\n" + " country(code: \"BR\") {\n" + " name\n" + " native\n" + " capital\n" + " emoji\n" + " currency\n" + " languages {\n" + " code\n" + " name\n" + " }\n" + " }\n" + "}"; ResponseEntity<String> response = restTemplate.postForEntity(url, new HttpEntity<>(query, headers), String.class); System.out.println(response.getBody()); } }
内容的提问来源于stack exchange,提问作者Praveenks
相关产品推荐
相关产品推荐

