คำขอ 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 ด้านล่าง
troyfolger

ปัญหาเหล่านี้ส่วนใหญ่เกี่ยวข้องกับการกำหนดค่าเซิร์ฟเวอร์ API คุณทดสอบ Server API โดยใช้ไคลเอนต์แบบสแตนด์อโลน (เช่นบุรุษไปรษณีย์) และจำลองส่วนหัวเดียวกันในคำขอของคุณ อย่างน้อยก็ในกรณีของฉันที่ทำเคล็ดลับ
Linus

1
@ จอห์นนี่บีถ้าได้รับคำตอบโปรดทำเครื่องหมายคำตอบ
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 ที่ใช้พารามิเตอร์เดียว
Constantino Cronemberger

24
วิธีการ.put()คือvoid!
Membersound

4
ใช้postForEntity(url, entity, String.class)ผลงานแทนput(url, entity)
Janac Meena

1
@Kanu, requestJson เป็น JSON String ที่ถูกต้องหรืออย่างอื่น?
Deva

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 เฉพาะปลายทางส่วนที่เหลือของฉันใช้เครื่องหมายคำพูดคู่ที่จำเป็นรอบ ๆ ชื่อเขตข้อมูลดังนั้นฉันจึงหลีกเลี่ยงเครื่องหมายคำพูดคู่ใน requestJson String ของฉัน


ได้โปรดช่วยฉันในstackoverflow.com/questions/42240927/…
FaisalAhmed

Spring สามารถใช้ตัวแปลงข้อความเพื่อแปลง Java Object เป็น json โดยอัตโนมัติเหมือนกับที่ทำใน Restful API ด้วย RestTemplate ได้หรือไม่
ตก

1
การตั้งค่าประเภทสื่อเป็น APPLICATION_JSON เป็นกุญแจสำคัญในการแก้ไขปัญหา
Pete T

ฉันแก้ไขปัญหาโดยใช้เอนทิตี HttpEntity <String> = ใหม่ HttpEntity <String> (requestJson, headers); บรรทัดนี้
Ved Prakash

76

ฉันใช้เทมเพลต rest กับ 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 ที่แม่นยำ
Simon

1
วิธีการพัฒนาโค้ดด้านบนสำหรับสิ่งนี้: curl -vvv -X POST " localhost: 8080 / SillyService_SRC / oauth / … "?
Pra_A

@Mikael Lepistöฉันจะดึงพารามิเตอร์เหล่านี้จาก json ที่เซิร์ฟเวอร์สิ้นสุดได้อย่างไร?
KJEjava48

@ KJEjava48 ฉันไม่เข้าใจว่าคุณหมายถึงอะไร ... นี่คือรหัสฝั่งเซิร์ฟเวอร์ในการตอบกลับ หากคุณกำลังคิดว่าจะแยกวิเคราะห์การตอบสนองของ json อย่างไรขึ้นอยู่กับกรอบงานที่คุณใช้
Mikael Lepistö

@ MikaelLepistöฉันหมายถึงวิธีแยกวิเคราะห์การตอบสนองของ json ในส่วนอื่น ๆ รวมถึงวิธีรับการตอบกลับใน java ?? คุณได้โพสต์เฉพาะรหัสสำหรับปลายด้านเดียว (เช่นฝั่งเซิร์ฟเวอร์)
KJEjava48


10

หากคุณใช้ Spring 3.0 วิธีง่ายๆในการหลีกเลี่ยงorg.springframework.web.client.HttpClientErrorException: 415ข้อยกเว้นประเภทสื่อที่ไม่รองรับคือการรวมไฟล์ jar jackson ไว้ใน classpath ของคุณและใช้mvc:annotation-drivenองค์ประกอบ config ตามที่ระบุไว้นี้ .

ฉันดึงผมออกเพื่อพยายามหาสาเหตุว่าทำไมแอปmvc-ajax จึงทำงานได้โดยไม่มีการกำหนดค่าพิเศษสำหรับไฟล์MappingJacksonHttpMessageConverter. หากคุณอ่านบทความที่ฉันเชื่อมโยงไว้ข้างต้นอย่างใกล้ชิด:

ภายใต้ฝาครอบ Spring MVC จะมอบหมายให้ HttpMessageConverter ทำการซีเรียลไลเซชัน ในกรณีนี้ Spring MVC จะเรียกใช้ MappingJacksonHttpMessageConverter ที่สร้างขึ้นบนโปรเซสเซอร์ Jackson JSON การดำเนินการนี้จะเปิดใช้โดยอัตโนมัติเมื่อคุณใช้ MVC: องค์ประกอบการกำหนดค่าคำอธิบายประกอบที่ขับเคลื่อนด้วยแจ็คสันอยู่ใน classpath


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's 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 ในฤดูใบไม้ผลิ:

@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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.