POST-запит через RestTemplate в JSON


126

Я не знайшов приклад, як вирішити свою проблему, тому хочу попросити вас допомогти. Я не можу просто надіслати запит POST, використовуючи об’єкт RestTemplate в JSON

Кожен раз, коли я отримую:

org.springframework.web.client.HttpClientErrorException: 415 Тип непідтримуваного носія

Я використовую RestTemplate таким чином:

...
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);

У чому я винен?


1
@troyfolger URL більше не діє
Noremac

Дякую - це посилання працює на цей текст: spring.io/guides/gs/consuming-rest
troyfolger

Щоб вирішити конкретну проблему з ОП вище, ви, мабуть, не вистачаєте заголовка HTTP із відповідним типом вмісту, див. Відповідь від morganw09dev нижче.
troyfolger

Ці проблеми в основному стосуються конфігурації сервера API. Ви перевіряєте серверний API за допомогою окремого клієнта (наприклад, Postman) і копіюєте ті самі заголовки у своєму запиті. Принаймні, в моєму випадку це зробив трюк.
Лінус

1
@Johnny B, якщо на це відповіли, будь ласка, позначте відповідь
Vishal

Відповіді:


162

Ця методика працювала для мене:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);

Я сподіваюся, що це допомагає


3
будь ласка, поясніть, у який рядок має бути повернутий результат http запиту
gstackoverflow

Для мене не потрібно було вказувати жодні заголовки. Я використав HttpEntity, який приймає один параметр.
Константіно Кронембергер

24
метод .put()є void!
члени звучання

4
Використання postForEntity(url, entity, String.class)творів замістьput(url, entity)
Janac Meena

1
@Kanu, requestJson дійсний рядок JSON або щось інше?
Дева

95

Я зіткнувся з цією проблемою при спробі налагодити кінцеву точку REST. Ось основний приклад використання класу RestTemplate Spring для створення запиту POST, який я використовував. Мені знадобилося досить багато часу, щоб зібрати код з різних місць, щоб отримати робочу версію.

RestTemplate restTemplate = new RestTemplate();

String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

Конкретний синтаксичний аналізатор JSON, який використовував мою кінцеву точку відпочинку, використовував необхідні подвійні лапки навколо імен полів, тому я уникнув подвійних лапок у своєму запитіJson String.


може у будь ласка , допоможіть мені в цьому stackoverflow.com/questions/42240927 / ...
FaisalAhmed

Чи може Spring використовувати перетворювачі повідомлень для автоматичного перетворення об’єкта Java в json, як це було в API Restful з RestTemplate?
падіння

1
Встановлення типу носія на APPLICATION_JSON - це ключ до вирішення проблеми.
Піт T

Я вирішив свою проблему, використовуючи HttpEntity <String> сутність = новий HttpEntity <String> (запитJson, заголовки); цей рядок
Вед Пракаш

76

Я використовував шаблон відпочинку з JSONObjects таким чином:

// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);

// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);

// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
  .exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
  JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
  // nono... bad credentials
}

Дякую - метод JSONObject toString був для мене корисним, він допоміг мені точно визначити свій JSONString.
Саймон

1
Як розробити вищезгаданий код для цього: curl -vvv -X POST " localhost: 8080 / SillyService_SRC / oauth / ... "?
Pra_A

@Mikael Lepistö Як я можу отримати ці параметри з json на кінці сервера ??
KJEjava48

@ KJEjava48 Я не розумію, що ти маєш на увазі ... це відповідь на стороні сервера у відповіді. Якщо ви думаєте, як розібрати відповідь json, це залежить від рамки, яку ви використовуєте.
Mikael Lepistö

@ MikaelLepistö Я маю на увазі, як проаналізувати відповідь json на іншому кінці, включаючи, як отримати відповідь у java ?? Ви розмістили лише код для одного кінця (тобто на стороні сервера).
KJEjava48

13

Як зазначено тут , я думаю , вам потрібно додати messageConverterдля MappingJacksonHttpMessageConverter


10

Якщо ви використовуєте Spring 3.0, простий спосіб уникнути org.springframework.web.client.HttpClientErrorException: 415 Виняток непідтримуваного типу медіа - це включення файлів jar-jackson у ваш classpath та використання mvc:annotation-drivenконфігураційного елемента. Як зазначено тут .

Я витягував волосся, намагаючись з’ясувати, чому програма mvc-ajax працює без особливих конфігурацій для MappingJacksonHttpMessageConverter. Якщо ви читаєте статтю, яку я зв'язав вище, уважно:

Під обкладинками Spring MVC делегує HttpMessageConverter для виконання серіалізації. У цьому випадку Spring MVC викликає MappingJacksonHttpMessageConverter, побудований на процесорі Jackson JSON. Ця реалізація ввімкнена автоматично, коли ви використовуєте конфігураційний елемент mvc: анотації з присутнім Джексоном у вашому класі .


7

Помилка "415 непідтримуваний тип медіа" повідомляє вам, що сервер не прийме ваш запит POST. Ваш запит абсолютно нормальний, це неправильно налаштований сервер.

MappingJacksonHttpMessageConverterавтоматично встановить заголовок типу вмісту запиту на application/json, і я гадаю, що ваш сервер це відкидає. Ви нічого не сказали нам про налаштування вашого сервера, тому я не можу вам порадити з цього приводу.


7

Я роблю таким чином, і це працює.

HttpHeaders headers = createHttpHeaders(map);
public HttpHeaders createHttpHeaders(Map<String, String> map)
{   
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    for (Entry<String, String> entry : map.entrySet()) {
        headers.add(entry.getKey(),entry.getValue());
    }
    return headers;
}

// Тут передайте заголовки

 String requestJson = "{ // Construct your JSON here }";
logger.info("Request JSON ="+requestJson);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
logger.info("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
logger.info("Response ="+response.getBody());

Сподіваюся, це допомагає


4

У мене виникла ця проблема, і я використовую Spring's RestTemplate на клієнті та Spring Web на сервері. Обидва API мають дуже погану звітність про помилки, що робить їх надзвичайно важкими для розробки.

Після багатьох годин спроб всіляких експериментів я з'ясував, що проблема викликана передачею нульової посилання для тіла POST замість очікуваного Списку. Я припускаю, що RestTemplate не може визначити тип вмісту з нульового об'єкта, але не скаржиться на нього. Після додавання правильних заголовків я почав отримувати інший виняток на сервері навесні, перш ніж вводити свій метод обслуговування.

Виправлення повинно було пройти у клієнта порожній список замість null. Не потрібні заголовки, оскільки тип вмісту за замовчуванням використовується для ненульових об'єктів.


3

Цей код працює для мене;

RestTemplate restTemplate = new RestTemplate();
Payment payment = new Payment("Aa4bhs");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("payment", payment);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headerObject);

Payment res = restTemplate.postForObject(url, httpEntity, Payment.class);

Я використовую дуже подібний підхід, і він НЕ працює для мене. чомусь мій еквівалент вашої "карти" не перетворюється на json або не включається як вихідний орган, тобто цільова служба НЕ бачить корисного навантаження.
абдель

2

Якщо ви не хочете обробляти відповідь

private RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(serviceURL, request, Void.class);

Якщо вам потрібна відповідь на процес

String result = restTemplate.postForObject(url, entity, String.class);

0

Для мене сталася помилка при цьому налаштуванні:

AndroidAnnotations Spring Android RestTemplate Module і ...

GsonHttpMessageConverter

Анотації на Android мають певні проблеми з цим перетвореним для створення POSTзапиту без параметра. Просто параметр new Object()вирішив це для мене.


0

Чому працювати важче, ніж треба? postForEntityприймає простий Mapоб'єкт як вхідний. Наступне працює добре для мене під час написання тестів на задану кінцеву точку REST навесні. Я вважаю, що це найпростіший можливий спосіб зробити запит JSON POST навесні:

@Test
public void shouldLoginSuccessfully() {
  // 'restTemplate' below has been @Autowired prior to this
  Map map = new HashMap<String, String>();
  map.put("username", "bob123");
  map.put("password", "myP@ssw0rd");
  ResponseEntity<Void> resp = restTemplate.postForEntity(
      "http://localhost:8000/login",
      map,
      Void.class);
  assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
}

0

Якщо ви не хочете власноруч відображати JSON, ви можете зробити це наступним чином:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<String> result = restTemplate.postForEntity(uri, yourObject, String.class);

0

Я спробував наступне у весняному завантаженні:

ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
public Map<String, Object> processResponse(String urlendpoint)
{
    try{
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //reqobj
        JSONObject request = new JSONObject();
        request.put("username", name);
        //Or Hashmap 
        Map<String, Object> reqbody =  new HashMap<>();
        reqbody.put("username",username);
        Gson gson = new Gson();//mvn plugin to convert map to String
        HttpEntity<String> entity = new HttpEntity<>( gson.toJson(reqbody), headers);
        ResponseEntity<Map<String, Object>> response = resttemplate.exchange(urlendpoint, HttpMethod.POST, entity, typeRef);//example of post req with json as request payload
        if(Integer.parseInt(response.getStatusCode().toString()) == HttpURLConnection.HTTP_OK)
        {
            Map<String, Object>  responsedetails = response.getBody();
            System.out.println(responsedetails);//whole json response as map object
            return responsedetails;
        }
    } catch (Exception e) {
        // TODO: handle exception
        System.err.println(e);
    }
    return null;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.