【问题标题】:How do I implement a PATCH executed via RestTemplate?如何实现通过 RestTemplate 执行的 PATCH?
【发布时间】:2025-08-06 20:35:02
【问题描述】:

我正在编写 JUnit 测试代码,通过 RestTemplate 调用我的应用程序。我已经成功实现了 GET、POST 和 PUT,但无法运行 PATCH(尽管它在客户端发送 URL 时有效)。例如,POST 使用以下代码运行:

    RestTemplate restTemplate = new RestTemplate(); 
    ProductModel postModel = restTemplate.postForObject(TestBase.URL + URL, pModel, ProductModel.class);            

但是当我尝试调用我在网上找到的 restTemplate.patchForObject() 时,STS 返回一个错误,指出该函数未定义。因此我使用了这个:

    RestTemplate restTemplate = new RestTemplate(); 
    ResponseEntity<MessageModel> retval = restTemplate.exchange("http://localhost:8080/products/batchUpdateProductPositions", 
            HttpMethod.PATCH, new HttpEntity<ProductPositionListModel>(pps), MessageModel.class);   

编译,但给我一个错误:

I/O Error on PATCH request for "http://localhost:8080/products/batchUpdateProductPositions": Invalid HTTP method: PATCH

在应用程序中,我在 Controller 类中定义了操作:

@RequestMapping(value = "/batchUpdateProductPositions", method = RequestMethod.PATCH)
public MessageModel batchUpdatePosition(
        @RequestBody ProductPositionListModel productPositionList)
        throws Exception {
    try {
        return productService.batchUpdatePosition(productPositionList);
    } catch (Exception e) {

我在 'try' 块内的 return 语句上设置了一个断点,但是当我在调试下运行它时它从未跳闸。

谁能告诉我我在哪里绊倒了?

【问题讨论】:

标签: java rest junit resttemplate http-patch


【解决方案1】:

默认情况下,RestTemplate 使用标准 JDK HttpURLConnection HTTP 客户端发出请求。此客户端不支持PATCH 方法。您可以通过客户端工厂配置RestTemplate 以使用其他HTTP 客户端,例如HttpComponentsClientHttpRequestFactoryOkHttpClientHttpRequestFactory

HttpClient client = HttpClients.createDefault();
RestTemplate template= new RestTemplate();
template.setRequestFactory(new HttpComponentsClientHttpRequestFactory(client)); 

您还需要添加适当的依赖项,例如 org.apache.httpcomponents:httpclient:$version 以防 HTTP 组件客户端。

【讨论】:

    【解决方案2】:

    我发现了一个与 JUnit 代码的其余部分保持一致的解决方案。使用 postForObject(),你可以传入你在这种情况下需要的 HTTP 方法:

        MessageModel pModel = restTemplate.postForObject(TestBase.URL + URL + "/batchUpdateProductPositions?_method=patch", 
                pps, MessageModel.class);           
    

    这运行正确。不能说是否有我没有注意到的副作用。

    【讨论】:

    • here 是解释。
    【解决方案3】:

    这对我有用,用于使用 RestTemplate 执行 PATCH 请求:

    RestTemplate restTemplate = new RestTemplate();
    
    HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
    httpRequestFactory.setConnectTimeout(timeout);
    httpRequestFactory.setReadTimeout(timeout);
    
    restTemplate.setRequestFactory(httpRequestFactory);
    

    现在将此 restTemplate 与 exchange() 一起使用。

    必需的依赖

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency> 
    

    【讨论】:

      【解决方案4】:

      试试这个:

      import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
      //...
      RestTemplate rest = new RestTemplate(new HttpComponentsClientHttpRequestFactory())
      
      //Now make the PATCH call using Exchange
      ResponseEntity<Map<String, Object>> response = rest.exchange(api, HttpMethod.PATCH, request, responseType);
      

      不要忘记将其添加到您的依赖项中:

      <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.4.1</version>
       </dependency>
      

      【讨论】:

        【解决方案5】:

        这个解决方案

        MessageModel pModel = restTemplate.postForObject(TestBase.URL + URL + "/batchUpdateProductPositions?_method=patch",pps, MessageModel.class);   
        

        如果您使用的是 Post 方法(@PostMapping)很有用,如果您想使用 Patch 方法(@PatchMapping),试试这个:

        restTemplate.patchForObject("http://localhost:8080/products/batchUpdateProductPositions", requestEntity, String.class);
        

        【讨论】:

          最近更新 更多