RestTemplate 指南

本贴最后更新于 1915 天前,其中的信息可能已经事过境迁

RestTemplate 指南

1 说明

在本教程中,我们将说明并很好地使用 Spring REST Client – RestTemplate 的各种操作。
对于所有示例的 API 方面,我们将从此处运行 RESTful 服务。
https://github.com/eugenp/tutorials/tree/master/spring-rest

2 使用 GET 检索资源

2.1 获取 JSON

让我们开始简单并讨论 GET 请求-使用 getForEntity() API,示例:

RestTemplate restTemplate = new RestTemplate();
String fooResourceUrl
  = "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response
  = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

请注意,我们拥有对 HTTP 响应的完全访问权限-因此我们可以执行诸如检查状态代码以确保操作成功或使用响应的正文之类的操作。

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.getBody());
JsonNode name = root.path("name");
assertThat(name.asText(), notNullValue());

我们在此处将响应主体作为标准 String,使用 Jackson(以及 Jackson 提供的 JSON 节点结构)来验证一些细节。

2.2 检索 POJO 而不是 JSON

我们还可以将响应直接映射到一个 DTO 对象 –例如:

public class Foo implements Serializable {
    private long id;
 
    private String name;
    // standard getters and setters
}

现在,我们只需使用 restTemplate.getForObject API:

Foo foo = restTemplate
  .getForObject(fooResourceUrl + "/1", Foo.class);
assertThat(foo.getName(), notNullValue());
assertThat(foo.getId(), is(1L));

3 使用 HEAD 检索 Headers

现在,让我们快速浏览一下使用 HEAD,然后再继续使用更常见的方法-我们将在这里使用 headForHeaders()API:

HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl);
assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON));

4 使用 POST 创建资源

为了在 API 中创建新的资源–我们可以充分利用 postForLocation(),postForObject()或 postForEntity()API。
第一个返回新创建的资源的 URI,而第二个返回资源本身。

4.1 postForObject API

RestTemplate restTemplate = new RestTemplate();
 
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
assertThat(foo, notNullValue());
assertThat(foo.getName(), is("bar"));

4.2 postForLocation API

让我们看一下该操作–而不是返回完整的 Resource,而是返回该新创建的 Resource 的 Location:

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
URI location = restTemplate
  .postForLocation(fooResourceUrl, request);
assertThat(location, notNullValue());

4.3 exchange API

让我们看一下如何使用更通用的 exchange API 进行 POST:

RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
  
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
  
Foo foo = response.getBody();
  
assertThat(foo, notNullValue());
assertThat(foo.getName(), is("bar"));

4.4 提交表单

接下来,让我们看看如何使用 POST 方法提交表单。
首先,我们需要将 ``Content-Type''标头设置为 application / x-www-form-urlencoded。
这样可以确保可以将一个较大的查询字符串发送到服务器,其中包含以“&”分隔的名称/值对:

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

我们可以将表单变量包装到 LinkedMultiValueMap 中:

MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("id", "1");

接下来,我们使用 HttpEntity 实例构建请求:

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

最后,我们可以通过在端点上调用 restTemplate.postForEntity()连接到 REST 服务:/foos/form

ResponseEntity<String> response = restTemplate.postForEntity(
  fooResourceUrl+"/form", request , String.class);
  
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

5 使用 OPTIONS 获取允许的操作

接下来,我们将快速了解如何使用 OPTIONS 请求,并使用这种请求探索对特定 URI 的允许操作;
API 是 optionsForAllow:

Set<HttpMethod> optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl);
HttpMethod[] supportedMethods
  = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};
assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));

6 使用 PUT 更新资源

接下来,我们将开始研究 PUT,并且由于 template.put API 非常简单,因此将更具体地说明此操作的 exchange API。

6.1 exchange 的简单 PUT

我们将从针对 API 的简单 PUT 操作开始-并记住该操作不会使任何人返回到客户端:

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(createResponse.getBody().getId());
String resourceUrl = 
  fooResourceUrl + '/' + createResponse.getBody().getId();
HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedInstance, headers);
template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);

6.2 带有.exchange 和请求回调的 PUT

下面,我们将使用请求回调来发出 PUT。
让我们确保我们准备了回调–在这里我们可以设置所需的所有标头以及请求正文:

RequestCallback requestCallback(final Foo updatedInstance) {
    return clientHttpRequest -> {
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(clientHttpRequest.getBody(), updatedInstance);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass());
    };
}

下一步,我们使用 POST 请求创建 Resource:

ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

然后我们更新资源:

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(response.getBody().getId());
String resourceUrl =fooResourceUrl + '/' + response.getBody().getId();
restTemplate.execute(
  resourceUrl, 
  HttpMethod.PUT, 
  requestCallback(updatedInstance), 
  clientHttpResponse -> null);

7 使用 DELETE 删除资源

要删除现有资源,我们使用 delete() API:

String entityUrl = fooResourceUrl + "/" + existingResource.getId();
restTemplate.delete(entityUrl);

8 配置超时

我们可以简单地使用 ClientHttpRequestFactory 将 RestTemplate 配置超时,如下所示:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
 
private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
      = new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}

我们可以将 HttpClient 用于其他配置选项-如下所示:

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    RequestConfig config = RequestConfig.custom()
      .setConnectTimeout(timeout)
      .setConnectionRequestTimeout(timeout)
      .setSocketTimeout(timeout)
      .build();
    CloseableHttpClient client = HttpClientBuilder
      .create()
      .setDefaultRequestConfig(config)
      .build();
    return new HttpComponentsClientHttpRequestFactory(client);
}

结语

我们遍历了主要的 HTTP 动词,使用 RestTemplate 来协调所有这些请求。
如果您想深入了解如何使用模板进行身份验证,请查看我关于使用 RestTemplate 进行基本身份验证的文章。
所有这些示例和代码段的实现都可以在我的 GitHub 项目中找到–这是一个基于 Maven 的项目,因此应该很容易直接导入和运行。

  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...