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

Чтобы решить конкретную проблему OP, описанную выше, возможно, вам не хватает заголовка HTTP с соответствующим типом содержимого, см. Ответ от morganw09dev ниже.
тройфолгер

Эти проблемы в основном связаны с конфигурацией API сервера. Вы тестируете серверный API с помощью автономного клиента (например, Postman) и реплицируете те же заголовки в свой запрос. По крайней мере, в моем случае это помогло.
Linus

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!
membersound

4
Использование postForEntity(url, entity, String.class)произведений вместоput(url, entity)
Янак Мина

1
@Kanu, requestJson - это действительная строка JSON или что-то еще?
Deva

95

Я столкнулся с этой проблемой при попытке отладки конечной точки REST. Вот базовый пример использования класса Spring RestTemplate для выполнения запроса 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, моя конечная точка отдыха, использовал необходимые двойные кавычки вокруг имен полей, поэтому я избежал двойных кавычек в моем requestJson String.


не могли бы вы помочь мне в этом stackoverflow.com/questions/42240927/…
FaisalAhmed

Может ли Spring использовать конвертеры сообщений для автоматического преобразования объекта Java в json, как это было в Restful API с RestTemplate?
осень

1
Установка типа носителя на APPLICATION_JSON - ключ к решению проблемы.
Pete T

Я решил свою проблему, используя HttpEntity <String> entity = new HttpEntity <String> (requestJson, headers); this line
Ved Prakash

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, это зависит от используемой вами структуры.
Микаэль Леписто

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


10

Если вы используете Spring 3.0, простой способ избежать исключения org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type - включить файлы jar jackson в путь к классам и использовать mvc:annotation-drivenэлемент config. Как указано здесь .

Я вытаскивал волосы, пытаясь понять, почему приложение mvc-ajax работает без какой-либо специальной конфигурации для MappingJacksonHttpMessageConverter. Если вы внимательно прочитали статью, на которую я ссылался выше:

Под обложками Spring MVC делегирует HttpMessageConverter для выполнения сериализации. В этом случае Spring MVC вызывает MappingJacksonHttpMessageConverter, построенный на процессоре Jackson JSON. Эта реализация включается автоматически, когда вы используете элемент конфигурации, управляемый аннотациями mvc: с присутствием Джексона в вашем пути к классам .


7

Ошибка «415 Unsupported Media Type» сообщает вам, что сервер не примет ваш 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 RestTemplate на клиенте и Spring Web на сервере. Оба API имеют очень плохую систему отчетов об ошибках, что чрезвычайно затрудняет их разработку.

После многих часов попыток всевозможных экспериментов я понял, что проблема была вызвана передачей нулевой ссылки для тела POST вместо ожидаемого списка. Я предполагаю, что RestTemplate не может определить тип содержимого по нулевому объекту, но не жалуется на это. После добавления правильных заголовков я начал получать в Spring другое исключение на стороне сервера перед тем, как ввести свой метод обслуживания.

Исправление заключалось в передаче от клиента пустого списка вместо нуля. Заголовки не требуются, поскольку тип содержимого по умолчанию используется для ненулевых объектов.


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 или не включается в качестве исходящего тела, т.е. целевая служба НЕ видит никакой полезной нагрузки.
abdel

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 в Spring. Я считаю, что это самый простой из возможных способов сделать запрос JSON POST в Spring:

@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.