ClientConfigExample.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package space.anyi.httpClient;
  2. import java.io.IOException;
  3. import java.net.CookieManager;
  4. import java.net.ProxySelector;
  5. import java.net.URI;
  6. import java.net.http.HttpClient;
  7. import java.net.http.HttpRequest;
  8. import java.net.http.HttpResponse;
  9. import java.net.http.HttpResponse.BodyHandlers;
  10. import java.time.Duration;
  11. import java.util.concurrent.Executors;
  12. /**
  13. * HTTP Client 配置项示例
  14. *
  15. * <p>通过 {@code HttpClient.newBuilder()} 返回的 Builder 可以配置客户端的
  16. * 通用行为,主要配置项如下:</p>
  17. *
  18. * <table>
  19. * <tr><th>配置项</th><th>作用</th><th>备注</th></tr>
  20. * <tr><td>version()</td><td>HTTP 协议版本</td><td>HTTP_1_1 / HTTP_2</td></tr>
  21. * <tr><td>connectTimeout()</td><td>连接建立超时时间</td><td>超过则抛 ConnectTimeoutException</td></tr>
  22. * <tr><td>executor()</td><td>异步请求使用的线程池</td><td>不设置则用内置默认线程池</td></tr>
  23. * <tr><td>followRedirects()</td><td>重定向策略</td><td>NEVER / ALWAYS / NORMAL</td></tr>
  24. * <tr><td>proxy()</td><td>代理选择器</td><td>NO_PROXY 直连</td></tr>
  25. * <tr><td>cookieHandler()</td><td>Cookie 管理器</td><td>配合 CookieManager 使用</td></tr>
  26. * <tr><td>authenticator()</td><td>认证器</td><td>配合 Authenticator 使用(Basic Auth 等)</td></tr>
  27. * <tr><td>sslContext/sslParameters()</td><td>TLS 配置</td><td>仅 HTTPS 生效</td></tr>
  28. * <tr><td>priority()</td><td>HTTP/2 流优先级</td><td>仅 HTTP_2 生效</td></tr>
  29. * </table>
  30. */
  31. public class ClientConfigExample {
  32. /** 服务基地址常量 */
  33. private static final String BASE_URL = "http://localhost:8080";
  34. /**
  35. * 构建一个携带多项配置的 HttpClient。
  36. *
  37. * <p>所有配置均为「在客户端创建时一次性设定」,创建后不可修改。</p>
  38. *
  39. * @return 配置完善的 HttpClient
  40. */
  41. public HttpClient buildConfiguredClient() {
  42. // Cookie 管理器(Index: CookieManager 负责保存/发送 Cookie)
  43. CookieManager cookieManager = new CookieManager();
  44. return HttpClient.newBuilder()
  45. // 指定 HTTP 协议版本为 1.1(本服务仅支持 HTTP/1.1)
  46. .version(HttpClient.Version.HTTP_1_1)
  47. // 连接建立超过 5 秒未成功则失败
  48. .connectTimeout(Duration.ofSeconds(5))
  49. // 自定义异步任务的执行线程池(默认是内置线程池)
  50. .executor(Executors.newFixedThreadPool(4))
  51. // 重定向策略:NORMAL 只自动跟随「安全方法」的重定向
  52. .followRedirects(HttpClient.Redirect.NORMAL)
  53. // 不使用代理,直连
  54. .proxy(ProxySelector.getDefault())
  55. // 配置 Cookie 管理器,自动管理会话 Cookie
  56. .cookieHandler(cookieManager)
  57. .build();
  58. }
  59. /**
  60. * 构建启用 HTTP/2 的客户端(本服务不支持,仅演示配置写法)。
  61. */
  62. public HttpClient buildHttp2Client() {
  63. return HttpClient.newBuilder()
  64. .version(HttpClient.Version.HTTP_2)
  65. // priority 仅对 HTTP/2 生效,范围 1~256,越大优先级越高
  66. .priority(256)
  67. .build();
  68. }
  69. /**
  70. * 使用配置好的客户端发送 GET 请求。
  71. *
  72. * @return GET /api/users 的响应
  73. */
  74. public HttpResponse<String> sendGet() throws IOException, InterruptedException {
  75. HttpClient httpClient = buildConfiguredClient();
  76. HttpRequest request = HttpRequest.newBuilder()
  77. .uri(URI.create(BASE_URL + "/api/users"))
  78. .GET()
  79. .build();
  80. return httpClient.send(request, BodyHandlers.ofString());
  81. }
  82. /**
  83. * 演示「连接超时」配置:连接不存在的地址应快速失败并抛异常。
  84. */
  85. public void demoConnectTimeout() {
  86. HttpClient client = HttpClient.newBuilder()
  87. .connectTimeout(Duration.ofSeconds(2))
  88. .build();
  89. HttpRequest request = HttpRequest.newBuilder()
  90. // 使用一个不存在的端口,模拟连接超时
  91. .uri(URI.create("http://localhost:9999"))
  92. .GET()
  93. .build();
  94. try {
  95. client.send(request, BodyHandlers.ofString());
  96. } catch (java.net.http.HttpConnectTimeoutException e) {
  97. System.out.println("连接超时: " + e.getMessage());
  98. } catch (IOException | InterruptedException e) {
  99. System.out.println("请求异常: " + e.getMessage());
  100. }
  101. }
  102. }