Permintaan POST melalui RestTemplate di JSON

126

Saya tidak menemukan contoh bagaimana menyelesaikan masalah saya, jadi saya ingin meminta bantuan Anda. Saya tidak bisa begitu saja mengirim permintaan POST menggunakan objek RestTemplate di JSON

Setiap kali saya mendapatkan:

org.springframework.web.client.HttpClientErrorException: 415 Jenis Media Tidak Didukung

Saya menggunakan RestTemplate dengan cara ini:

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

Apa kesalahanku?

Johnny B
sumber
1
@troyfolger url tidak lagi valid
Noremac
Terima kasih - tautan ini berfungsi pada tulisan ini: spring.io/guides/gs/consuming-rest
troyfolger
Untuk mengatasi masalah OP tertentu di atas, Anda mungkin kehilangan header HTTP dengan jenis konten yang sesuai, lihat jawaban dari morganw09dev di bawah.
troyfolger
Masalah ini sebagian besar terkait dengan konfigurasi API Server. Anda menguji API Server menggunakan klien Standalone (seperti Postman) dan mereplikasi header yang sama dalam permintaan Anda. Setidaknya dalam kasus saya, itulah Trik.
Linus
1
@Johnny B, jika ini telah dijawab tolong tandai jawabannya
Vishal

Jawaban:

162

Teknik ini berhasil untuk saya:

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

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

saya harap ini membantu

kanu dialani
sumber
3
tolong jelaskan baris mana yang harus mengembalikan hasil permintaan http
gstackoverflow
Bagi saya, tidak perlu menentukan header apa pun. Saya telah menggunakan HttpEntity yang mengambil parameter tunggal.
Constantino Cronemberger
24
metode .put()adalah void!
Memberound
4
Menggunakan postForEntity(url, entity, String.class)karya di tempatput(url, entity)
Janac Meena
1
@Kan, request adalah String JSON yang valid atau yang lainnya?
Deva
95

Saya mengalami masalah ini saat mencoba men-debug titik akhir REST. Berikut adalah contoh dasar menggunakan kelas RestTemplate Spring untuk membuat permintaan POST yang saya gunakan. Butuh waktu lama bagi saya untuk mengumpulkan kode dari berbagai tempat untuk mendapatkan versi yang berfungsi.

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

Parser JSON tertentu, titik akhir istirahat saya menggunakan tanda kutip ganda yang diperlukan di sekitar nama bidang jadi itulah mengapa saya lolos dari tanda kutip ganda di String requestJson saya.

Morgan Kenyon
sumber
bisakah kamu membantu saya di stackoverflow.com/questions/42240927/…
FaisalAhmed
Dapatkah Spring menggunakan pengonversi pesan untuk secara otomatis mengonversi Objek Java ke json seperti yang dilakukan di Restful API dengan RestTemplate?
jatuh
1
Menyetel jenis media ke APPLICATION_JSON adalah kunci untuk menyelesaikan masalah.
Pete T
Saya menyelesaikan masalah saya menggunakan HttpEntity <String> entity = new HttpEntity <String> (requestJson, headers); baris ini
Ved Prakash
76

Saya telah menggunakan template istirahat dengan JSONObjects sebagai berikut:

// 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
}
Mikael Lepistö
sumber
Terima kasih - metode toString JSONObject berguna bagi saya, ini membantu saya mendapatkan akurasi JSONString saya.
Simon
1
Bagaimana mengembangkan kode di atas untuk ini: curl -vvv -X POST " localhost: 8080 / SillyService_SRC / oauth /… "?
Pra_A
@ Mikael Lepistö Bagaimana cara mengambil parameter ini dari json di server end ??
KJEjava48
@ KJEjava48 Saya tidak mengerti apa yang Anda maksud ... ini adalah kode sisi server sebagai tanggapan. Jika Anda berpikir bagaimana mengurai respons json, itu tergantung pada kerangka kerja yang Anda gunakan.
Mikael Lepistö
@ MikaelLepistö Maksud saya bagaimana mem-parsing respons json di ujung lain termasuk cara menerima respons di java ?? Anda hanya memposting kode untuk satu ujung (yaitu, sisi server).
KJEjava48
13

Seperti yang ditentukan di sini, saya rasa Anda perlu menambahkan messageConverteruntuk MappingJacksonHttpMessageConverter

Raghuram
sumber
10

Jika Anda menggunakan Spring 3.0, cara mudah untuk menghindari org.springframework.web.client.HttpClientErrorException: 415 Pengecualian Jenis Media yang Tidak Didukung , adalah dengan menyertakan file jar jackson di jalur kelas Anda, dan menggunakan mvc:annotation-drivenelemen config. Seperti yang ditentukan di sini .

Saya menarik rambut saya mencoba mencari tahu mengapa aplikasi mvc-ajax bekerja tanpa konfigurasi khusus untuk file MappingJacksonHttpMessageConverter. Jika Anda membaca artikel yang saya tautkan di atas dengan cermat:

Di bawah sampul, Spring MVC mendelegasikan ke HttpMessageConverter untuk melakukan serialisasi. Dalam kasus ini, Spring MVC memanggil MappingJacksonHttpMessageConverter yang dibangun di atas prosesor Jackson JSON. Implementasi ini diaktifkan secara otomatis saat Anda menggunakan elemen konfigurasi mvc: annotation-driven dengan Jackson hadir di classpath Anda .

Mike G
sumber
7

Kesalahan "415 Jenis Media Tidak Didukung" memberi tahu Anda bahwa server tidak akan menerima permintaan POST Anda. Permintaan Anda baik-baik saja, itu adalah server yang salah konfigurasi.

MappingJacksonHttpMessageConverterakan secara otomatis mengatur header tipe konten permintaan ke application/json, dan perkiraan saya adalah bahwa server Anda menolaknya. Anda belum memberi tahu kami apa pun tentang penyiapan server Anda, jadi saya tidak bisa benar-benar memberi tahu Anda tentang itu.

skaffman
sumber
7

Saya melakukan dengan cara ini dan berhasil.

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

// Berikan header di sini

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

Semoga ini membantu

Yakhoob
sumber
4

Saya mendapatkan masalah ini dan saya menggunakan Spring's RestTemplate di klien dan Spring Web di server. Kedua API memiliki pelaporan kesalahan yang sangat buruk, membuatnya sangat sulit untuk dikembangkan.

Setelah berjam-jam mencoba semua jenis eksperimen, saya menemukan bahwa masalahnya disebabkan oleh memberikan referensi nol untuk badan POST, bukan Daftar yang diharapkan. Saya berasumsi bahwa RestTemplate tidak dapat menentukan tipe konten dari objek null, tetapi tidak mengeluh tentang itu. Setelah menambahkan header yang benar, saya mulai mendapatkan pengecualian sisi server yang berbeda di Spring sebelum memasuki metode layanan saya.

Perbaikannya adalah meneruskan List kosong dari klien, bukan null. Tidak ada header yang diperlukan karena tipe konten default digunakan untuk objek bukan nol.

Alex Worden
sumber
3

Kode ini berfungsi untuk saya;

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);
Ganesh
sumber
saya menggunakan pendekatan yang sangat mirip dan TIDAK berhasil untuk saya. untuk beberapa alasan yang setara dengan 'peta' saya tidak sedang dikonversi ke json atau dimasukkan sebagai badan keluar yaitu, layanan target TIDAK melihat muatan apa pun.
abdel
2

Jika Anda tidak ingin memproses respons

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

Jika Anda membutuhkan respons untuk memproses

String result = restTemplate.postForObject(url, entity, String.class);
Vipindas Gopalan
sumber
0

Bagi saya, kesalahan terjadi dengan penyiapan ini:

AndroidAnnotations Spring Android RestTemplate Module dan ...

GsonHttpMessageConverter

Anotasi Android memiliki beberapa masalah dengan ini dikonversi untuk menghasilkan POSTpermintaan tanpa parameter. Cukup parameter new Object()memecahkannya untuk saya.

Mateusz Jablonski
sumber
0

Mengapa bekerja lebih keras dari yang Anda harus? postForEntitymenerima Mapobjek sederhana sebagai input. Berikut ini berfungsi dengan baik untuk saya saat menulis tes untuk titik akhir REST tertentu di Spring. Saya percaya ini adalah cara yang paling sederhana untuk membuat permintaan JSON POST di 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);
}
eriegz
sumber
0

Jika Anda tidak ingin memetakan JSON sendiri, Anda dapat melakukannya sebagai berikut:

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

Saya mencoba sebagai berikut di boot musim semi:

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;
}
Parameshwar
sumber