【问题标题】:restTemplate delete with bodyrestTemplate 用正文删除
【发布时间】:2016-08-22 07:56:17
【问题描述】:

我正在尝试对请求正文执行 DELETE,但我不断收到 400(错误请求)错误。当我在招摇/邮递员中这样做时,它成功删除了记录。但是从Java代码我不能这样做

外部 API 的设计方式是它需要正文和 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;
        }
    }

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

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

【问题讨论】:

  • 您已经在requestEntity 中有一个请求正文。检查您的 API 并查看它的预期。然后检查你的身体是否序列化到你所期望的。
  • 请求正文相同。同一机构正在为 POST 和 PUT 工作。从具有相同值的 swagger UI 中删除工作正常,但在 java 代码中失败
  • 这里没有足够的细节让我们帮助您。向我们展示 Swagger 通过网络发送的内容。向我们展示RestTemplate 示例发送的内容。到那时,您可能会自己找到答案。
  • 我做了 CustomObjectMapper mapper = new CustomObjectMapper();和调试 mapper.writeValueAsString(person) 和 java 代码登录的相同请求在 Swagger UI 中工作正常。想知道会是什么问题
  • 您链接到的错误是不言自明的。 java

标签: java spring rest resttemplate spring-rest


【解决方案1】:

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

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

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

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

if ("PUT".equals(httpMethod) || "POST".equals(httpMethod) ||     
         "PATCH".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}

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

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

然后创建您的RestTemplate 对象

RestTemplate template = new RestTemplate(
                            new CustomClientHttpRequestFactory());

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

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

【讨论】:

    【解决方案2】:

    解决此问题的另一种方法是使用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 */
    }
    

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

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 2023-01-16
      • 1970-01-01
      • 2020-11-17
      • 2019-09-27
      • 1970-01-01
      • 2020-09-30
      • 2012-05-17
      • 2017-09-14
      相关资源
      最近更新 更多