1. 概述

本文将介绍 Google HTTP Client Library for Java,这是一个通过 HTTP 连接协议访问资源的快速、高度抽象的库。

该客户端的主要特性包括:

HTTP 抽象层:解耦底层 HTTP 库实现
高效的 JSON/XML 解析:灵活处理请求/响应内容
便捷的注解系统:简化 HTTP 资源映射

该库兼容 Java 5 及以上版本,非常适合遗留项目(SE/EE)开发。本文将通过一个连接 GitHub API 获取用户信息的示例,展示库的核心功能。

2. Maven 依赖

首先添加核心依赖:

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client</artifactId>
    <version>1.23.0</version>
</dependency>

最新版本可在 Maven Central 查询。

3. 发起简单请求

通过一个简单的 GET 请求展示基本用法:

HttpRequestFactory requestFactory
  = new NetHttpTransport().createRequestFactory();
HttpRequest request = requestFactory.buildGetRequest(
  new GenericUrl("https://github.com"));
String rawResponse = request.execute().parseAsString();

核心组件说明:

组件 作用
HttpRequestFactory 构建请求对象
HttpTransport 底层 HTTP 传输抽象
GenericUrl URL 包装类
HttpRequest 执行实际请求

后续章节将结合实际 JSON API 演示更复杂场景。

4. 可插拔的 HTTP 传输

库提供了高度抽象的 HttpTransport 类,支持灵活切换底层 HTTP 实现

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
}

默认使用 NetHttpTransport(基于 HttpURLConnection),这是最可靠的选择。若需高级定制,可切换至 ApacheHttpTransport

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new ApacheHttpTransport();
}

ApacheHttpTransport 基于 Apache HttpClient,提供更丰富的连接配置选项。也支持自定义底层实现。

5. JSON 解析

库提供 JSON 解析抽象层,核心优势在于底层解析库可自由切换

5.1 可切换的解析库

以 Jackson2 实现为例,需添加依赖:

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client-jackson2</artifactId>
    <version>1.23.0</version>
</dependency>

初始化 JsonFactory

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    static JsonFactory JSON_FACTORY = new JacksonFactory();
}

⚠️ 性能权衡

  • JacksonFactory:速度最快(推荐),但库体积较大
  • GsonFactory:轻量级(基于 Google GSON),适合资源受限场景
  • 支持自定义解析器实现

5.2 @Key 注解

使用 @Key 标记需要序列化/反序列化的字段:

public class User {
    @Key
    private String login;
    @Key
    private long id;
    @Key("email")
    private String email;
    
    // 标准 getter/setter
}

关键规则:

  • ❌ 未标记 @Key 的字段会被忽略
  • ✅ 字段可见性不影响解析
  • ✅ 无需 getter/setter
  • 可通过 @Key("json_key") 指定 JSON 映射名

5.3 GenericJson

为保留未声明的 JSON 字段,可继承 GenericJson

public class User extends GenericJson {
    //...
}

GenericJson 实现了 Map 接口,支持动态存取 JSON 内容:

User user = new User();
user.put("extra_field", "value"); // 动态添加字段
String extra = (String) user.get("extra_field"); // 动态读取

6. 发起 API 调用

通过 HttpRequestFactory 整合传输层和解析层:

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    static JsonFactory JSON_FACTORY = new JacksonFactory();

    private static void run() throws Exception {
        HttpRequestFactory requestFactory 
          = HTTP_TRANSPORT.createRequestFactory(
            (HttpRequest request) -> {
              request.setParser(new JsonObjectParser(JSON_FACTORY));
          });
    }
}

创建 URL 类处理查询参数:

public class GitHubUrl extends GenericUrl {
    public GitHubUrl(String encodedUrl) {
        super(encodedUrl);
    }
    
    @Key
    public int per_page;
}

完整调用示例:

private static void run() throws Exception {
    HttpRequestFactory requestFactory
      = HTTP_TRANSPORT.createRequestFactory(
        (HttpRequest request) -> {
          request.setParser(new JsonObjectParser(JSON_FACTORY));
        });
    
    GitHubUrl url = new GitHubUrl("https://api.github.com/users");
    url.per_page = 10; // 设置每页用户数
    
    HttpRequest request = requestFactory.buildGetRequest(url);
    Type type = new TypeToken<List<User>>() {}.getType();
    List<User> users = (List<User>) request
      .execute()
      .parseAs(type);
}

关键步骤:

  1. 通过 GitHubUrl 设置查询参数
  2. 使用 TypeToken 处理泛型集合类型
  3. parseAs() 自动将响应映射为 List<User>

7. 自定义请求头

在请求执行前修改请求头:

HttpHeaders headers = request.getHeaders();
headers.setUserAgent("Baeldung Client");
headers.set("Time-Zone", "Europe/Amsterdam");

⚠️ 注意:

  • 部分头字段(如 User-Agent)有专用设置方法
  • 直接调用 set() 设置特殊头会抛出异常

8. 指数退避重试

实现基于状态码的智能重试机制:

ExponentialBackOff backoff = new ExponentialBackOff.Builder()
  .setInitialIntervalMillis(500)
  .setMaxElapsedTimeMillis(900000)
  .setMaxIntervalMillis(6000)
  .setMultiplier(1.5)
  .setRandomizationFactor(0.5)
  .build();
  
request.setUnsuccessfulResponseHandler(
  new HttpBackOffUnsuccessfulResponseHandler(backoff));

参数说明:

  • initialIntervalMillis:初始重试间隔(500ms)
  • maxElapsedTimeMillis:最大总重试时间(15分钟)
  • multiplier:间隔增长倍数(1.5倍)
  • randomizationFactor:随机抖动因子(0.5)

❌ 默认不启用,需显式设置 HttpUnsuccessfulResponseHandler

9. 日志配置

使用 java.util.logging.Logger 记录请求/响应细节。配置示例 logging.properties

handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
com.google.api.client.http.level = ALL

启动时指定配置文件:

-Djava.util.logging.config.file=logging.properties

日志输出示例:

-------------- REQUEST  --------------
GET https://api.github.com/users?page=1&per_page=10
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)

Nov 12, 2017 6:43:15 PM com.google.api.client.http.HttpRequest execute
curl -v --compressed -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)' -- 'https://api.github.com/users?page=1&per_page=10'

-------------- RESPONSE --------------
HTTP/1.1 200 OK
Status: 200 OK
Transfer-Encoding: chunked
Server: GitHub.com
Access-Control-Allow-Origin: *
...
Link: <https://api.github.com/users?page=1&per_page=10&since=19>; rel="next"
X-GitHub-Request-Id: 8D6A:1B54F:3377D97:3E37B36:5A08DC93
Content-Type: application/json; charset=utf-8
...

10. 总结

本文介绍了 Google HTTP Client 的核心功能:

  • 灵活的传输层抽象
  • 高效的 JSON 处理机制
  • 智能重试策略
  • 便捷的日志配置

更多细节请参考官方 GitHub 仓库。完整示例代码可在 教程仓库 获取。


原始标题:A Guide to Google-Http-Client