RestTemplate 与正文一起删除

Shi*_*iva 9 java rest spring resttemplate spring-rest

我正在尝试对请求正文进行 DELETE,但我不断收到 400(错误请求)错误。当我在 swagger/postman 中执行此操作时,它成功删除了记录。但从 Java 代码来看我无法做到这一点

外部 API 的设计方式需要 body 和 URL。它无法改变。请让我知道如何删除带有请求正文的条目

public Person delete(Person person, String url, Map<String, String> uriVariables) throws JsonProcessingException {
        RestTemplate restTemplate = new RestTemplate();
        CustomObjectMapper mapper = new CustomObjectMapper();
        HttpEntity<Person> requestEntity = new HttpEntity<Person>(person);
        try {
            ResponseEntity<Person> responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Person.class, uriVariables);
            return responseEntity.getBody();
        } catch (RestClientException e) {
            System.out.println(mapper.writeValueAsString(person));
            throw e;
        }
    }
Run Code Online (Sandbox Code Playgroud)

当出现异常时,我将获得 JSON 格式的 JSON 请求,并且在 Swagger/postman 中同样可以正常工作

我做了一些谷歌搜索,发现restTemplate在存在请求正文时存在删除问题。这篇文章没有帮助https://jira.spring.io/browse/SPR-12361有什么办法让它工作

Jim*_*and 10

解决此问题的另一种方法是使用restTemplate.exchange,这是一个示例:

try {
      String jsonPayload  = GSON.toJson(request);
      HttpEntity<String> entity = new HttpEntity<String>(jsonPayload.toString(),headers());
      ResponseEntity resp = restTemplate.exchange(url, HttpMethod.DELETE, entity, String.class);
} catch (HttpClientErrorException e) {
      /* Handle error */
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案的好处是您可以将它与所有 HttpMethod 类型一起使用。


Pra*_*tel 5

Spring 4.0.x 或更早版本存在问题。
在后来的版本中已修复。

这可能是一个迟到的答案,但在我的一个项目中,我通过自定义解决了这个ClientHttpRequestFactory问题RestTemplate

如果没有提供工厂RestTemplate,它将使用默认实现SimpleClientHttpRequestFactory

SimpleClientHttpRequestFactory类中,DELETE方法不允许与请求正文一起使用。

if ("PUT".equals(httpMethod) || "POST".equals(httpMethod) ||     
         "PATCH".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}
Run Code Online (Sandbox Code Playgroud)

只需将您自己的实现编写为

import java.io.IOException;
import java.net.HttpURLConnection;

import org.springframework.http.client.SimpleClientHttpRequestFactory;

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {

    @Override
    protected void prepareConnection(HttpURLConnection connection, 
            String httpMethod) throws IOException {

        super.prepareConnection(connection, httpMethod);
        if("DELETE".equals(httpMethod)) {
            connection.setDoOutput(true);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

之后将您的RestTemplate对象创建为

RestTemplate template = new RestTemplate(
                            new CustomClientHttpRequestFactory());
Run Code Online (Sandbox Code Playgroud)

在更高版本(4.1.x 或更高版本)SimpleClientHttpRequestFactory类中修复

if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) ||
            "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}
Run Code Online (Sandbox Code Playgroud)