2017-02-09 198 views
0

它已经困扰了两天已经是一个看似超级简单的问题:GET请求JSON

我做的application/json使用RestTemplate简单的GET请求,但一直收到

org.springframework.web.client.HttpClientErrorException: 400 Bad Request 
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) 
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:636) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:592) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:552) 
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:470) 

我做了研究并遵循了这个tutorial,我也查看了这个POST request via RestTemplate in JSON的解决方案。但他们没有帮助,这是我的代码:

RestTemplate restTemplate = new RestTemplate();  
HttpHeaders requestHeaders = new HttpHeaders();  
requestHeaders.setContentType(MediaType.APPLICATION_JSON); 
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders); 
restTemplate.exchange(endpoint, HttpMethod.GET, requestEntity, String.class); 

endpointhttp://localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8")这邮差工作正常。 itemIds是一个逗号分隔的列表如下图所示:

5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

我还试图用getForObject象下面这样:

String result = restTemplate.getForObject(endpoint, String.class); 

这给了我这个错误:

org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type 

我我不知道我错过了什么,或者错了什么,但是同样的终结点在Postman上完美工作,但是唯一的差异erence是我在Postman应用程序中添加了Content-Type标头。

这是邮差我的要求:

GET /api/v1/items?itemIds=abc%2cdef%2cghi HTTP/1.1 Host: localhost:8080 Connection: keep-alive Postman-Token: 84790e06-86aa-fa8a-1047-238d6c931a68 Cache-Control: no-cache User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Content-Type: application/json Accept: */* Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4

所以,我怎么能正确设置使用RestTemplate如果我上面的代码是错误的内容类型?

另一个深潜,我已经解雇了Wireshark捕捉到两个HTTP请求,下面是截图:

从邮差请求:request from Postman

从我的Java代码的请求:request from Java program

我仍然不明白为什么从我的Java程序中抛出400,而从邮差的工作正常。

非常感谢。

+0

你试过getForObject()和getForEntity()吗?他们可能比exchange更好()。 –

+0

转储您通过邮递员发送的请求并将其发布到此处。 –

+0

但是,为什么你使用GET请求的内容类型?内容类型是“请求主体的MIME类型(与POST和PUT请求一起使用)”。 https://en.wikipedia.org/wiki/List_of_HTTP_header_fields –

回答

0

确定,最终,我的同事的人帮助我想知道为什么,不管你信不信,这就是这么简单:

endpoint是这样的: "http:localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8");

但是,它应该是"http:localhost:8080/api/v1/items?itemIds=" + itemIds;

itemIds仅仅是一个逗号分隔的列表。

URLEncoder的编码后通过 “UTF-8” 模式,这个逗号分隔的列表变得itemIds=5400028914%2C5400029138%2C5400029138%2C5400029138%2C5400029138%2C5400028401%2C5400028918%2C5400028076

itemIds=5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

我们不需要使用URLEncoder的时候RestTemplate来编码URL ,任何人都可以帮助我加深我的理解吗?

谢谢!

0

你不需要设置 “requestEntity” 的GET方法,试试你的代码是这样的:

public ItemInfo getItemInfo() throws Exception { 
    String url = 
      "http://localhost:8080/api/v1/items?itemIds=abc"; 
    ObjectMapper objectMapper = new ObjectMapper();  
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class); 
    String responseBody = response.getBody(); 
    handlerError(response, url); 
    try { 
     return objectMapper.readValue(responseBody, ItemInfo.class); 
    } catch (IOException exception) { 
     LOGGER.error("failed to send REST request", exception); 
     throw new Exception(ErrorCode.NOT_AVAILABLE, url); 
    } 
} 

private void handlerError(final ResponseEntity<String> response, final String url) throws Exception { 
    String responseBody = response.getBody(); 
    try { 
     if (RestUtil.isError(response.getStatusCode())) { 
      ObjectMapper objectMapper = new ObjectMapper(); 
      MyInfoError myInfoError = objectMapper.readValue(responseBody, MyInfoError.class); 
      throw new Exception(infoErreur, ErrorCode.UNKNOWN_CODE_ERROR); 
     } else if (RestUtil.isNotFound(response.getStatusCode())) { 
      throw new Exception(ErrorCode.NOT_AVAILABLE, "MyService"); 
     } 
    } catch (IOException exception) { 
     LOGGER.error("failed to send REST request", exception); 
     throw new Exception(ErrorCode.NOT_AVAILABLE, url); 
    } 
} 

我把它放在NULL,因为GET方法不发送任何JSON请求体/标题:

restTemplate.exchange(url, HttpMethod.GET, null, String.class); 

OR:把你的头在GET方法是这样的:

RestTemplate restTemplate = new RestTemplate(); 
HttpHeaders headers = new HttpHeaders(); 
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); 
HttpEntity<?> requestEntity = new HttpEntity<>(headers); 
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); 

例如用于POST需要设置requestEntity象下面这样:

ItemFormRequest request = 
      new ItemFormRequest(1,"item no", "item name"); 
HttpEntity<ItemFormRequest> requestEntity = new HttpEntity<>(request); 
     ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); 
     String responseBody = response.getBody(); 

希望这有助于:)

+1

他们的'HttpEntity'没有任何内容。它只是作为这种情况下的标题容器。 –

+0

是的,你是对的。我改变了我的答案,因为它在这里迟到,我缺少一些问题信息:) 谢谢@SotiriosDelimanolis –

+1

你的代码现在等于他们的,所以我不明白你的答案的目的。 –