POST yêu cầu thông qua RestTemplate trong JSON


126

Tôi không tìm thấy bất kỳ ví dụ nào để giải quyết vấn đề của mình, vì vậy tôi muốn nhờ bạn giúp đỡ. Tôi không thể đơn giản gửi yêu cầu POST bằng cách sử dụng đối tượng RestTemplate trong JSON

Mỗi khi tôi nhận được:

org.springframework.web.client.HttpClientErrorException: 415 Loại phương tiện không được hỗ trợ

Tôi sử dụng RestTemplate theo cách này:

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

Lỗi của tôi là gì


1
@troy Scratchger url không còn hợp lệ
Noremac

Cảm ơn - liên kết này đang hoạt động như văn bản này: spring.io/guides/gs/consuming-rest
troyheadger

Để giải quyết vấn đề OP cụ thể, ở trên, có lẽ bạn đang thiếu một tiêu đề HTTP với loại nội dung phù hợp, hãy xem câu trả lời từ morganw09dev bên dưới.
troyreasger

Các vấn đề này chủ yếu liên quan đến cấu hình API máy chủ. Bạn kiểm tra API máy chủ bằng ứng dụng khách Độc lập (như Người đưa thư) và sao chép các tiêu đề tương tự trong yêu cầu của bạn. Ít nhất trong trường hợp của tôi đã làm Trick.
Linus

1
@ John B, nếu điều này đã được trả lời, vui lòng đánh dấu câu trả lời
Vishal

Câu trả lời:


161

Kỹ thuật này đã làm việc cho tôi:

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

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

Tôi hi vọng cái này giúp được


3
vui lòng giải thích hàng nào sẽ trả về kết quả của yêu cầu http
gstackoverflow

Đối với tôi không cần thiết phải chỉ định bất kỳ tiêu đề nào. Tôi đã sử dụng HTTPEntity có một tham số duy nhất.
Constantino Cronemberger

24
phương pháp .put()void!
viên

4
Sử dụng postForEntity(url, entity, String.class)các công trình thay choput(url, entity)
Janac Meena

1
@Kanu, requestJson là Chuỗi JSON hợp lệ hay cái gì khác?
Deva

95

Tôi đã gặp vấn đề này khi cố gắng gỡ lỗi điểm cuối REST. Dưới đây là một ví dụ cơ bản sử dụng lớp RestTemplate của Spring để tạo một yêu cầu POST mà tôi đã sử dụng. Tôi đã mất khá nhiều thời gian để ghép mã từ các nơi khác nhau để có được một phiên bản hoạt động.

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

Trình phân tích cú pháp JSON cụ thể mà điểm cuối còn lại của tôi đang sử dụng các dấu ngoặc kép cần thiết xung quanh các tên trường, vì vậy đó là lý do tại sao tôi đã thoát khỏi dấu ngoặc kép trong chuỗi requestJson của mình.


Bạn có thể vui lòng giúp tôi về stackoverflow.com/questions/42240927/ từ
FaisalAhmed

Spring có thể sử dụng các trình chuyển đổi thông báo để tự động chuyển đổi Đối tượng Java thành json như đã làm trong Restful API với RestTemplate không?
rơi

1
Đặt loại phương tiện thành ỨNG DỤNG_JSON là chìa khóa để giải quyết vấn đề.
Pete T

Tôi đã giải quyết vấn đề của mình bằng cách sử dụng HttpEntity <String> entity = new HttpEntity <String> (requestJson, headers); dòng này
Ved Prakash

76

Tôi đã sử dụng mẫu nghỉ ngơi với JSONObjects như sau:

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

Cảm ơn - phương thức JSONObject toString rất hữu ích cho tôi, nó đã giúp tôi có được JSONString chính xác.
Simon

1
Làm cách nào để phát triển mã trên cho việc này: curl -vvv -X POST " localhost: 8080 / SillyService_SRC / oauth / Lỗi "?
Pra_A

@Mikael Lepistö Làm thế nào tôi có thể lấy các tham số này từ json ở cuối máy chủ ??
KJEjava48

@ KJEjava48 Tôi không hiểu ý bạn là gì ... đây là mã phía máy chủ trong phản hồi. Nếu bạn đang nghĩ làm thế nào để phân tích phản hồi json, nó phụ thuộc vào khuôn khổ mà bạn đang sử dụng.
Mikael Lepistö

@ MikaelLepistö Ý tôi là làm thế nào để phân tích phản hồi json ở đầu kia bao gồm cả cách nhận phản hồi trong java ?? Bạn chỉ đăng mã cho một đầu (ví dụ: phía máy chủ).
KJEjava48

13

Theo quy định ở đây tôi đoán bạn cần phải thêm một messageConvertercho MappingJacksonHttpMessageConverter


9

Nếu bạn đang sử dụng Spring 3.0, một cách dễ dàng để tránh org.springframework.web.client.HttpClientErrorException: 415 Ngoại lệ Loại phương tiện không được hỗ trợ , là bao gồm các tệp jar jackson trong đường dẫn lớp của bạn và sử dụng mvc:annotation-drivenphần tử cấu hình. Theo quy định tại đây .

Tôi đang kéo tóc ra để cố gắng tìm ra lý do tại sao ứng dụng mvc-ajax hoạt động mà không có cấu hình đặc biệt nào cho MappingJacksonHttpMessageConverter. Nếu bạn đọc bài viết tôi liên kết chặt chẽ ở trên:

Bên dưới vỏ bọc, Spring MVC ủy quyền cho một HTTPMessageConverter để thực hiện việc tuần tự hóa. Trong trường hợp này, Spring MVC gọi MappingJacksonHttpMessageConverter được xây dựng trên bộ xử lý Jackson JSON. Việc triển khai này được kích hoạt tự động khi bạn sử dụng phần tử cấu hình hướng đến mvc: chú thích với Jackson có trong đường dẫn lớp của bạn .


7

Lỗi "Loại phương tiện không được hỗ trợ" 415 cho bạn biết rằng máy chủ sẽ không chấp nhận yêu cầu POST của bạn. Yêu cầu của bạn là hoàn toàn tốt, đó là máy chủ được cấu hình sai.

MappingJacksonHttpMessageConvertersẽ tự động đặt tiêu đề loại nội dung yêu cầu application/jsonvà tôi đoán là máy chủ của bạn đang từ chối điều đó. Tuy nhiên, bạn chưa nói với chúng tôi bất cứ điều gì về thiết lập máy chủ của bạn, vì vậy tôi thực sự không thể tư vấn cho bạn về điều đó.


7

Tôi đang làm theo cách này và nó hoạt động.

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

// Truyền tiêu đề vào đây

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

Hi vọng điêu nay co ich


4

Tôi đã gặp vấn đề này và tôi đang sử dụng RestTemplate của Spring trên máy khách và Spring Web trên máy chủ. Cả hai API đều có báo cáo lỗi rất kém, khiến chúng cực kỳ khó phát triển.

Sau nhiều giờ thử tất cả các loại thí nghiệm, tôi phát hiện ra rằng vấn đề đã được gây ra bằng cách chuyển vào một tham chiếu null cho phần thân POST thay vì Danh sách dự kiến. Tôi đoán rằng RestTemplate không thể xác định loại nội dung từ một đối tượng null, nhưng không phàn nàn về nó. Sau khi thêm các tiêu đề chính xác, tôi bắt đầu nhận được một ngoại lệ phía máy chủ khác trong Spring trước khi nhập phương thức dịch vụ của mình.

Cách khắc phục là chuyển vào Danh sách trống từ máy khách thay vì null. Không có tiêu đề được yêu cầu vì loại nội dung mặc định được sử dụng cho các đối tượng không null.


3

Mã này đang làm việc cho tôi;

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

tôi đang sử dụng một cách tiếp cận rất giống nhau và nó KHÔNG hiệu quả với tôi. vì một số lý do, tương đương với 'bản đồ' của tôi không được chuyển đổi thành json hoặc được bao gồm dưới dạng nội dung bên ngoài, tức là dịch vụ đích KHÔNG thấy bất kỳ tải trọng nào.
abdel

2

Nếu bạn không muốn xử lý phản hồi

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

Nếu bạn cần phản hồi để xử lý

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

0

Đối với tôi xảy ra lỗi với thiết lập này:

AndroidAnnotations Spring Android RestTemplate Module và ...

GsonHttpMessageConverter

Chú thích Android có một số vấn đề với điều này được chuyển đổi để tạo POSTyêu cầu mà không có tham số. Chỉ cần tham số new Object()giải quyết nó cho tôi.


0

Tại sao phải làm việc chăm chỉ hơn bạn? postForEntitychấp nhận một Mapđối tượng đơn giản làm đầu vào. Phần sau đây hoạt động tốt với tôi trong khi viết bài kiểm tra cho điểm cuối REST đã cho trong Spring. Tôi tin rằng đó là cách đơn giản nhất có thể để thực hiện một yêu cầu JSON POST trong 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

Nếu bạn không muốn tự ánh xạ JSON, bạn có thể làm như sau:

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

0

Tôi đã thử như sau trong khởi động mùa xuân:

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.