> For the complete documentation index, see [llms.txt](https://potoyang.gitbook.io/spring-in-action-v4/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://potoyang.gitbook.io/spring-in-action-v4/di-16-zhang-shi-yong-spring-mvc-chuang-jian-rest-api/untitled-1.md).

# 16.4　编写 REST 客户端

作为客户端，编写与 REST 资源交互的代码可能会比较乏味，并且所编写的代码都是样板式的。例如，假设我们需要借助 Facebook 的 Graph API，编写方法来获取某人的 Facebook 基本信息。不过，获取基本信息的代码会有点复杂，如下面的程序清单所示。

{% code title="程序清单 16.6 使用 Apache HTTP Client 获取 Facebook 中的个人基本信息" %}

```java
public Profile fetchFacebookProfile(String id) {
  try {
    HttpClient client = HttpClients.createDefault();
    HttpGet request = new HttpGet("http://graph.facebook.com/" + id);
    request.setHeader("Accept", "application/json");
    
    HttpResponse response = client.execute(request);

    HttpEntity entity = response.getEntity();
    ObjectMapper mapper = new ObjectMapper();
    
    return mapper.readValue(entity.getContent(), Profile.class);
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
}
```

{% endcode %}

你可以看到，在使用 REST 资源的时候涉及很多代码。这里我甚至还偷懒使用了 Jakarta Commons HTTP Client 发起请求并使用 Jackson JSON processor 解析响应。

仔细看一下 fetchFacebookProfile() 方法，你可能会发现方法中只有少量代码与获取 Facebook 个人信息直接相关。如果你要编写另一个方法来使用其他的 REST 资源，很可能会有很多代码是与 fetchFacebookProfile() 相同的。

另外，还有一些地方可能会抛出的 IOException 异常。因为 IOException 是检查型异常，所以要么捕获它，要么抛出它。在本示例中，我选择捕获它并在它的位置重新抛出一个非检查型异常 RuntimeException。

鉴于在资源使用上有如此之多的样板代码，你可能会觉得最好的方式是封装通用代码并参数化可变的部分。这正是 Spring 的 RestTemplate 所做的事情。就像 JdbcTemplate 处理了 JDBC 数据访问时的丑陋部分，RestTemplate 让我们在使用 RESTful 资源时免于编写那些乏味的代码。

稍后，我们将会看到如何借助 RestTemplate 重写 fetchFacebookProfile() 方法，这会戏剧性的简化该方法并消除掉样板式代码。但首先，让我们整体了解一下 RestTemplate 提供的所有 REST 操作。
