2017-02-09 10 views
0

Это беспокоило в течение нескольких дней уже, казалось бы, очень простой вопрос:GET в RestTemplate в формате JSON

Я сделать простой запрос GET с использованием RestTemplate в application/json, но я получаю

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); 

endpoint является http://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 

I «Я не уверен, что я пропустил или сделал не так, но тот же конечный пункт отлично работает на Postman, но единственный diff что я добавил заголовок Content-Type в приложении Postman.

Это мой запрос от Почтальон:

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, в то время как один из Postman работает нормально.

Большое спасибо.

+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 для кодирования URL при использовании RestTemplate , кто-нибудь мог бы помочь мне углубить мое понимание здесь, пожалуйста?

Спасибо!

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); 

ИЛИ: положить ваши заголовки в методе 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

Ваш код теперь эквивалентен их, поэтому я не понимаю цели вашего ответа. –