HttpUtils工具类 httpclient5+okhttp

HttpUtils工具类(一)常见的HttpUtils工具类及如何自定义java的http连接池-CSDN博客

一、几种常见的Http调用方式

  1. Apache HttpClient
  2. OKhttpClient
  3. Hutool封装的HttpUtils
  4. Spring RestTemplate
  5. Java 原生的HttpURLConnection

 

1. 使用 Apache HttpClient

Apache HttpClient 是一个功能强大的 HTTP 客户端库,支持同步和异步请求。它适用于处理更加复杂的场景,如认证、连接池、多线程、上传文件等。

 

特点

  • 功能强大:Apache HttpClient 是一个久经考验的库,支持多种复杂的场景,包括连接池、代理、认证、重定向、Cookie 管理等。
  • 扩展性好:可以通过丰富的 API 进行灵活配置,满足复杂的企业级应用需求。
  • 同步阻塞:Apache HttpClient 默认是同步阻塞模式,适用于同步请求。

优点

  • 成熟稳定,经过长时间的验证,企业级项目中广泛使用。
  • 适合需要复杂 HTTP 操作的场景,如带有重试、认证和状态维护的请求。

缺点

  • 比较重量级,学习曲线稍陡峭。

maven依赖:

 
  1. <dependency>
  2. <groupId>org.apache.httpcomponents</groupId>
  3. <artifactId>httpclient</artifactId>
  4. <version>4.5.13</version>
  5. </dependency>
 

2. 使用 OKhttpClient

官网(概述 - OkHttp (square.github.io)

OKhttpClient是一个轻量级且性能出色的 HTTP 客户端,支持同步和异步请求,广泛应用于 Android 开发中。

特点

  • 轻量级且高效:OkHttpClient 是由 Square 开发的轻量级 HTTP 客户端库,广泛用于 Android 开发中。
  • 同步与异步请求:支持同步阻塞和异步非阻塞请求,异步操作非常简单且性能良好。
  • 连接复用:内置连接池,减少重复连接带来的开销,尤其适合在 Android 和 Web 应用中使用。

优点

  • 性能优异,尤其适合移动端和需要高并发的场景。
  • API 简单易用,支持异步调用,非常适合需要频繁发起网络请求的应用场景。

缺点

  • 功能相对较少,某些复杂功能需要自定义扩展。

 

maven依赖:

 
  1. <dependency>
  2. <groupId>com.squareup.okhttp3</groupId>
  3. <artifactId>okhttp</artifactId>
  4. <version>4.9.0</version>
  5. </dependency>
 

 

3. 使用第三方库(Hutool)的http链接池

官网(Http客户端工具类-HttpUtil (hutool.cn)

Hutool-http针对JDK的HttpUrlConnection做一层封装,简化了HTTPS请求、文件上传、Cookie记忆等操作,使Http请求变得无比简单。

Hutool-http的核心集中在两个类:

  • HttpRequest
  • HttpResponse

同时针对大部分情境,封装了HttpUtil工具类。

优点:

  1. 根据URL自动判断是请求HTTP还是HTTPS,不需要单独写多余的代码。
  2. 表单数据中有File对象时自动转为multipart/form-data表单,不必单做做操作。
  3. 默认情况下Cookie自动记录,比如可以实现模拟登录,即第一次访问登录URL后后续请求就是登录状态。
  4. 自动识别304跳转并二次请求
  5. 自动识别页面编码,即根据header信息或者页面中的相关标签信息自动识别编码,最大可能避免乱码。
  6. 自动识别并解压Gzip格式返回内容

特点

  • 工具化封装:Hutool 是一个 Java 工具库,其封装的 HttpUtils 提供了简洁的 API,用于发送 HTTP 请求。与 Apache HttpClient 和 OkHttp 相比,Hutool 封装的 HttpUtils 更加简化和易用,适合快速开发。
  • 轻量级:Hutool 的封装非常轻量,主要面向日常开发中的小型任务。
  • 默认处理:支持自动化处理请求头、超时、编码等,开发者只需关注核心业务逻辑。

优点

  • API 简单易用,能快速上手,适合需要快速开发和简洁代码的项目。
  • Hutool 提供了丰富的其他工具类,整合使用可以大大提升开发效率。

缺点

  • 不适合处理过于复杂的 HTTP 场景,定制化能力弱于 Apache HttpClient 和 OkHttp。
  • 适用于一般场景下的快速开发,复杂场景可能需要自行扩展或使用其他库。

maven依赖:

 
  1. <dependency>
  2. <groupId>cn.hutool</groupId>
  3. <artifactId>hutool-all</artifactId>
  4. <version>5.8.16</version>
  5. </dependency>
 

 

4. 使用 Spring RestTemplate

RestTemplate 是 Spring 提供的用于调用 RESTful Web 服务的工具类,简化了发送 HTTP 请求和处理响应的操作。

 

5. 使用 Java 原生的HttpURLConnection

HttpURLConnection 是 Java 自带的用于发送 HTTP 请求的类。它适合处理简单的 GET、POST 请求,但对于更复杂的需求(如多部分表单数据上传、流式处理等),需要自己编写更多的代码

 

二、总结

  • 简单场景HttpURLConnection 和 RestTemplate、Hutools的HttpUtils
  • 复杂场景Apache HttpClient 和 OkHttpClient,用于处理认证、连接池、文件上传等定制化需求。

 

常用三种HttpUtils对比总结

  • Apache HttpClient:适用于复杂的企业级应用,功能齐全,特别是在处理高级 HTTP 功能如认证、代理、连接池等方面表现出色。
  • OkHttpClient:轻量级且高效,适合高并发、移动端应用(如 Android 开发)以及需要异步请求的场景,性能好且使用简单。
  • Hutool 封装的 HttpUtils:工具类封装简洁,适合快速开发和处理简单的 HTTP 请求,适合轻量级项目。

可以根据项目需求选择合适的工具可以有效简化 HTTP 请求的处理逻辑。

 

 

=======================================================

 接下来,将围绕

  1. Apache HttpClient
  2. OKhttpClient

这两种自定义Http连接池,并列举相应的例子。

HttpUtils工具类(二)Apache HttpClient 5 使用详细教程_apache client5-CSDN博客

一、Apache HttpClient 5介绍

Apache HttpClient 5 是一个功能齐全且高度可定制的 HTTP 客户端库, 其专门用于发送 HTTP 请求、处理 HTTP 响应并支持各种 HTTP 协议特性。特别适合处理复杂的 HTTP 请求需求,如多协议支持、认证、连接池、代理等。它适合中大型项目或需要高级 HTTP 特性的应用开发。

 

(1)核心特性

  1. 功能强大:

    • 同步与异步支持:支持同步和异步的 HTTP 请求处理,异步请求在处理大量并发请求时能够显著提高效率。
    • 连接池管理:内置的连接池机制能提高并发处理性能,减少资源消耗。
    • 多种认证机制:支持多种认证方式,包括 Basic、Digest、NTLM、Kerberos 等,能够处理多种安全场景。
    • 支持Cookie管理:内置 Cookie 管理功能,能够自动处理服务端返回的 Cookie 并在后续请求中使用,模拟浏览器行为。
  2. 协议支持广泛:

    • HTTP/1.1 和 HTTP/2 支持:支持现代 HTTP 协议,包括 HTTP/2 的多路复用和流优先级等特性,提升了网络请求效率;特别是 HTTP/2 多路复用的优势。
    • SSL/TLS 支持:支持 HTTPS,提供自定义 SSL/TLS 配置,确保通信的安全性。HttpClient 5 可以方便地处理 HTTPS 请求,支持定制化的 SSL/TLS 配置。
  3. 灵活性和可扩展性:

    • 易于扩展和定制:允许开发者根据需要进行灵活的定制,HttpClient 5 的设计高度模块化,用户可以根据需要对连接管理、重定向策略、请求重试策略、代理设置等进行灵活定制。
    • 代理支持:可以轻松配置 HTTP 或 SOCKS 代理,用于跨网络访问和隐私保护。
  4. 健壮的错误处理机制:

    • 自动重试和重定向处理:内置的重试机制和自动重定向处理,可以减少由于网络问题导致的失败请求。开发者可以定制是否启用自动重定向。

 

(2)Apache HttpClient 5 的新特性

与之前的 4.x 版本相比,HttpClient 5 进行了大量的改进和优化,特别是在性能和安全性方面:

  • HTTP/2 支持:提供了完整的 HTTP/2 支持,包括多路复用、流优先级等特性。
  • 更好的异步支持:在处理并发请求时,通过异步模型极大提升了响应速度和吞吐量。
  • 灵活的响应处理:通过改进的响应处理 API,可以更方便地处理大型响应体,避免内存溢出问题。

 

(3)在 Java 项目的主要使用场景及缺点

使用场景:

  1. RESTful API 客户端:与第三方 API 交互,发送各种 HTTP 请求。
  2. Web 爬虫:抓取网页内容,处理重定向、Cookie 等。
  3. 分布式系统通信:用于微服务间的 HTTP 通信。
  4. 测试与自动化:模拟 HTTP 请求,进行集成和自动化测试。
  5. 代理与网关:处理请求代理和认证机制。
  6. 文件上传下载:实现大文件的传输。
  7. 认证交互:处理 OAuth2、JWT 等认证协议。
  8. 安全通信:处理 HTTPS 请求,确保数据安全。

缺点:

  1. 学习曲线陡峭:高级特性(如自定义连接池、SSL 配置、异步请求等)较为复杂,新手需要时间学习和掌握。
  2. 体积较大:相比轻量级客户端,如 OkHttp,HttpClient 依赖库较多,可能不适合小型项目。
  3. 性能消耗高:默认配置下的内存和 CPU 占用较高,需调整才能达到最佳性能。
  4. 配置繁琐:高级定制(如连接管理、认证、代理)需要较多配置,增加开发复杂度。
  5. 异步编程复杂:异步请求的回调、错误处理等逻辑复杂,增加代码难度。

 

二、在实际项目中的应用

(1)引入maven配置

首先,你需要将 HttpClient 5 的依赖加入到项目中。pom.xml 文件如下:

 
  1. <dependency>
  2. <groupId>org.apache.httpcomponents.client5</groupId>
  3. <artifactId>httpclient5</artifactId>
  4. <version>5.1</version>
  5. </dependency>
 
XML

(2)自定义HttpUtils工具类---实现连接管理、重试策略等

 
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.apache.hc.client5.http.DnsResolver;
  3. import org.apache.hc.client5.http.classic.methods.HttpPost;
  4. import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
  5. import org.apache.hc.client5.http.config.RequestConfig;
  6. import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
  7. import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
  8. import org.apache.hc.client5.http.impl.classic.HttpClients;
  9. import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
  10. import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
  11. import org.apache.hc.core5.http.HttpEntity;
  12. import org.apache.hc.core5.http.io.SocketConfig;
  13. import org.apache.hc.core5.http.message.BasicHeader;
  14. import org.apache.hc.core5.util.Timeout;
  15. import org.springframework.stereotype.Component;
  16.  
  17. import java.io.Closeable;
  18. import java.io.IOException;
  19. import java.net.InetAddress;
  20. import java.net.URI;
  21. import java.net.UnknownHostException;
  22. import java.util.Map;
  23.  
  24.  
  25. /**
  26. * @author 响叮当
  27. * @since 2024/8/15 14:10
  28. **/
  29. @Slf4j
  30. @Component
  31. public class ApacheHttpClientUtil {
  32.  
  33. private CloseableHttpClient httpClient;
  34.  
  35. @PostConstruct
  36. public void init() {
  37. SocketConfig socketConfig = SocketConfig.custom()
  38. .setSoTimeout(Timeout.ofMilliseconds(1000))
  39. .build();
  40.  
  41. PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder
  42. .create()
  43. .setDefaultSocketConfig(socketConfig)
  44. .setMaxConnTotal(1000)
  45. .setMaxConnPerRoute(50)
  46. .build();
  47.  
  48. RequestConfig requestConfig = RequestConfig.custom()
  49. .setConnectionRequestTimeout(Timeout.ofMilliseconds(8000))
  50. .setResponseTimeout(Timeout.ofMilliseconds(8000))
  51. .setConnectTimeout(Timeout.ofMilliseconds(8000))
  52. .build();
  53.  
  54. httpClient = HttpClients
  55. .custom()
  56. .disableContentCompression()
  57. .setConnectionManager(connectionManager)
  58. .setDefaultRequestConfig(requestConfig)
  59. .build();
  60. }
  61.  
  62.  
  63. public CloseableHttpResponse getOrHead(String url, String method, Map<String, String> headers) throws IOException {
  64. HttpUriRequestBase request = new HttpUriRequestBase(method, URI.create(url));
  65. BasicHeader[] head = mapToHeaders(headers);
  66. request.setHeaders(head);
  67. return httpClient.execute(request);
  68. }
  69.  
  70.  
  71. public CloseableHttpResponse post(String url, Map<String, String> headers, HttpEntity httpEntity) throws IOException {
  72. HttpPost request = new HttpPost(url);
  73. BasicHeader[] head = mapToHeaders(headers);
  74. request.setHeaders(head);
  75. request.setEntity(httpEntity);
  76. return httpClient.execute(request);
  77. }
  78.  
  79. public static BasicHeader[] mapToHeaders(Map<String, String> map) {
  80. BasicHeader[] headers = new BasicHeader[map.size()];
  81. int i = 0;
  82. for (Map.Entry<String, String> entry : map.entrySet()) {
  83. headers[i++] = new BasicHeader(entry.getKey(), entry.getValue());
  84. }
  85. return headers;
  86. }
  87.  
  88. public static void closeQuietly(Closeable is) {
  89. if (is != null) {
  90. try {
  91. is.close();
  92. } catch (Exception ex) {
  93. log.error("Resources encounter an exception when closing,ex:{}", ex.getMessage());
  94. }
  95. }
  96. }
  97.  
  98. }
 
java

功能概述

  1. 初始化 HTTP 客户端init() 方法初始化 CloseableHttpClient,配置连接池、请求超时和套接字超时。
    • 连接池配置:通过 PoolingHttpClientConnectionManagerBuilder 设置最大连接数(1000)和每路由的最大连接数(50),用于高并发场景。
    • 请求配置:包括连接超时、请求超时和响应超时,确保在合理的时间内处理请求。
  2. HTTP 请求处理
    • GET/HEAD 请求getOrHead() 方法可发送 GET 或 HEAD 请求,并接受自定义请求头。
    • POST 请求post() 方法可发送 POST 请求,支持自定义请求头和实体。
  3. 资源管理closeQuietly() 方法用于关闭资源,避免抛出异常。

 

(3)代码中的具体实现

1、Get请求

 
  1. @GetMapping("/get")
  2. public void testGet() {
  3. String url = "http://xxx.com.cn";
  4. try {
  5. // 1、构建入参、添加 headers
  6. Map<String, String> headers = new HashMap<>();
  7.  
  8. // 2、发起http请求
  9. CloseableHttpResponse httpResponse = apacheHttpClientUtil.getOrHead(url, "GET", headers);
  10.  
  11. // 3、返回结果,异常处理
  12. if (httpResponse.getCode() == 200) {
  13. String resStr = EntityUtils.toString(httpResponse.getEntity());
  14. log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());
  15. } else {
  16. log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());
  17. }
  18. } catch (Exception e) {
  19. log.error("request_udmp_fail, ex:{}", e);
  20. }
  21. }
 
java

 

2、POST请求-常规

 
  1. @PostMapping("/post")
  2. public void testPost(@RequestBody PostReq req) {
  3. String url = "http://xxx.com.cn";
  4. try {
  5. // 1、构建入参、添加 headers
  6. StringEntity stringEntity = new StringEntity(JSONUtil.toJsonStr(req), ContentType.APPLICATION_JSON);
  7. Map<String, String> headers = new HashMap<>();
  8.  
  9. // 2、发起http请求
  10. CloseableHttpResponse httpResponse = apacheHttpClientUtil.post(url, headers, stringEntity);
  11.  
  12. // 3、返回结果,异常处理
  13. if (httpResponse.getCode() == 200) {
  14. String resStr = EntityUtils.toString(httpResponse.getEntity());
  15. log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());
  16. } else {
  17. log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());
  18. }
  19. } catch (Exception e) {
  20. log.error("request_udmp_fail, ex:{}", e);
  21. }
  22. }
 
java

 

3、POST请求-上传文件

 
  1. /**
  2. * 上传文件
  3. * @param multipartFile
  4. * @param token
  5. * @param key
  6. * @return
  7. */
  8. @PostMapping("/uploadFile")
  9. public UploadRes testPostFile(
  10. @RequestParam("file") MultipartFile multipartFile,
  11. @RequestParam("token") String token,
  12. @RequestParam("key") String key
  13. ) {
  14. UploadRes res = null;
  15. String url = "http://xxx.com.cn";
  16. try {
  17. // 1、构建File参数
  18. File file = new File(multipartFile.getOriginalFilename());
  19. try (FileOutputStream fos = new FileOutputStream(file)) {
  20. fos.write(multipartFile.getBytes());
  21. }
  22. MultipartEntityBuilder builder = MultipartEntityBuilder.create();
  23. builder.addBinaryBody("file", file, ContentType.MULTIPART_FORM_DATA, "ex.xlsx");
  24.  
  25. // 2、构建其他参数
  26. builder.addTextBody("token", token, ContentType.TEXT_PLAIN);
  27. builder.addTextBody("key", key, ContentType.TEXT_PLAIN);
  28. HttpEntity multipartEntity = builder.build();
  29.  
  30. // 3、需要加 header,在这里加
  31. Map<String, String> headers = new HashMap<>();
  32.  
  33. // 4、发起http请求
  34. CloseableHttpResponse httpResponse = apacheHttpClientUtil.post(url, headers, multipartEntity);
  35.  
  36. // 5、返回结果,异常处理
  37. if (httpResponse.getCode() == 200) {
  38. String resStr = EntityUtils.toString(httpResponse.getEntity());
  39. res = JSONUtil.toBean(resStr, UploadRes.class);
  40. log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());
  41. } else {
  42. log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());
  43. }
  44. } catch (Exception e) {
  45. log.error("request_udmp_fail, ex:{}", e);
  46. }
  47. return res;
  48. }
 
java

 

(4)高级用法

1、处理重定向

HttpClient 5 默认会处理 3XX 重定向,但你也可以自定义行为。

 
  1. CloseableHttpClient httpClient = HttpClients.custom()
  2. .disableRedirectHandling() // 禁用自动重定向
  3. .build();
 
java

 

2、SSL/TLS 支持

使用 HttpClient 5 可以轻松处理 HTTPS 请求,下面展示如何自定义 SSL 配置。

 
  1. import org.apache.hc.core5.ssl.SSLContextBuilder;
  2. import org.apache.hc.client5.http.impl.classic.HttpClients;
  3. import javax.net.ssl.SSLContext;
  4.  
  5. SSLContext sslContext = SSLContextBuilder.create()
  6. .loadTrustMaterial((chain, authType) -> true) // 信任所有证书
  7. .build();
  8.  
  9. CloseableHttpClient httpClient = HttpClients.custom()
  10. .setSSLContext(sslContext)
  11. .build();
 
java

 

3、处理异步请求

如果你需要发送异步 HTTP 请求,可以使用 HttpAsyncClient

 
  1. import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
  2. import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
  3. import org.apache.hc.core5.concurrent.FutureCallback;
  4. import org.apache.hc.client5.http.classic.methods.HttpGet;
  5.  
  6. CloseableHttpAsyncClient asyncClient = HttpAsyncClients.createDefault();
  7.  
  8. asyncClient.start();
  9.  
  10. HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");
  11.  
  12. asyncClient.execute(request, new FutureCallback<>() {
  13. @Override
  14. public void completed(CloseableHttpResponse response) {
  15. System.out.println("Response received: " + response.getCode());
  16. }
  17.  
  18. @Override
  19. public void failed(Exception ex) {
  20. System.out.println("Request failed: " + ex.getMessage());
  21. }
  22.  
  23. @Override
  24. public void cancelled() {
  25. System.out.println("Request cancelled");
  26. }
  27. });
 
java

4、处理 Cookie

 
  1. import org.apache.hc.client5.http.cookie.BasicCookieStore;
  2. import org.apache.hc.client5.http.impl.classic.HttpClients;
  3. import org.apache.hc.client5.http.cookie.CookieStore;
  4.  
  5. CookieStore cookieStore = new BasicCookieStore();
  6. CloseableHttpClient httpClient = HttpClients.custom()
  7. .setDefaultCookieStore(cookieStore)
  8. .build();
 
java

5、HTTPDNS支持

 
  1. // 当域名为www.baidu.com结尾时候,转到local的机器上
  2. String Target_IP= "127.0.0.1";
  3. String[] domains = new String[]{"www.baidu.com"};
  4.  
  5. DnsResolver dnsResolver = new DnsResolver() {
  6. @Override
  7. public InetAddress[] resolve(String host) throws UnknownHostException {
  8. if (host.endsWith(domains[0]))) {
  9. return new InetAddress[]{InetAddress.getByName(Target_IP)};
  10. }
  11. return new InetAddress[0];
  12. }
  13.  
  14. @Override
  15. public String resolveCanonicalHostname(String s) {
  16. return null;
  17. }
  18. };
  19.  
  20.  
  21. // @PostConstruct
  22. public void init() {
  23. SocketConfig socketConfig = SocketConfig.custom()
  24. .setSoTimeout(Timeout.ofMilliseconds(1000))
  25. .build();
  26.  
  27. PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder
  28. .create()
  29. .setDnsResolver(dnsResolver) // 这里是HttpDns配置
  30. .setDefaultSocketConfig(socketConfig)
  31. .setMaxConnTotal(1000)
  32. .setMaxConnPerRoute(50)
  33. .build();
 

HttpUtils工具类(三)OKHttpClient使用详细教程-CSDN博客

OkHttpClient 是一个由 Square 公司开发的 HTTP 客户端库,用于在 Android 和 Java 应用中进行网络请求。它支持同步和异步请求、连接池、超时设置、拦截器等功能,适合用于高性能网络请求,特别是在需要处理复杂的网络操作时。

 

一、OKHttpClient介绍

主要特点

  1. 同步和异步请求

    • 同步请求会在当前线程等待响应,适合不需要并发的简单请求。

    • 异步请求会将网络操作交由后台线程处理,不会阻塞主线程,适合需要并发处理或在 Android 等环境中使用。

  2. 连接池: OkHttp 默认会使用连接池来复用 HTTP 连接,从而提高性能,减少连接的建立和关闭的开销。

  3. 拦截器 (Interceptor): 拦截器允许在请求和响应时进行操作,例如可以在请求发送前添加认证信息,或在响应到达后进行日志记录。

  4. 自动处理 HTTP/2 和 SPDY: OkHttp 默认支持 HTTP/2 协议,可以提升多路复用性能,使多个请求共享一个 TCP 连接。

  5. 缓存机制: OkHttp 提供了默认的缓存机制,可以根据 HTTP 响应头自动缓存请求结果,减少重复网络请求。

  6. 超时控制: 可以对连接、读取和写入操作分别设置超时,避免长时间无响应的请求卡住应用。

 

 

二、在实际项目中的应用

(1)引入maven配置

 
  1. <!-- ok的Http连接池 -->    
  2. <dependency>
  3.    <groupId>com.squareup.okhttp3</groupId>
  4.    <artifactId>okhttp</artifactId>
  5.    <version>4.9.3</version>
  6. </dependency>
 
bash

(2)自定义HttpUtils工具类

 
  1. import com.alibaba.fastjson.JSONObject;
  2. import com.yan.project.httpUtils.okHttp2.HttpRequestBody;
  3. import lombok.extern.slf4j.Slf4j;
  4. import okhttp3.*;
  5.  
  6. import java.io.Closeable;
  7. import java.io.File;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import java.util.Map;
  11. import java.util.Objects;
  12. import java.util.Set;
  13. import java.util.concurrent.TimeUnit;
  14.  
  15. @Slf4j
  16. public class OkHttpUtils {
  17. private OkHttpUtils() {
  18. throw new IllegalArgumentException("Utility class");
  19. }
  20.  
  21. private static final String MIME_JSON = "application/json; charset=utf-8";
  22.  
  23. private static OkHttpClient httpClient = new OkHttpClient.Builder()
  24. .connectTimeout(3, TimeUnit.SECONDS)
  25. .writeTimeout(5, TimeUnit.SECONDS)
  26. .readTimeout(5, TimeUnit.SECONDS)
  27. .addInterceptor((Interceptor.Chain chain) -> {
  28. Request req = chain.request();
  29. try {
  30. Response res = chain.proceed(req);
  31. return res;
  32. } catch (Exception ex) {
  33. throw ex;
  34. }
  35. })
  36. .build();
  37.  
  38. // GET-无参
  39. public static String getJson(String url) throws IOException {
  40. return basicGet(url, null);
  41. }
  42.  
  43. // GET-有参
  44. public static String get(String url, Map<String, Object> paramMap) throws Exception {
  45. StringBuilder sb = new StringBuilder(url);
  46. if (paramMap != null && !paramMap.isEmpty()) {
  47. Set<String> keySet = paramMap.keySet();
  48. for (String key : keySet) {
  49. sb.append(sb.toString().contains("?") ? "&" : "?");
  50. sb.append(key).append("=").append(paramMap.get(key));
  51. }
  52. url = sb.toString();
  53. }
  54. return basicGet(url, null);
  55. }
  56.  
  57.  
  58. // GET-有参、有请求头
  59. public static String getWithHeades(String url, Map<String, Object> paramMap, Map<String, String> headers) throws Exception {
  60. StringBuilder sb = new StringBuilder(url);
  61. if (paramMap != null && !paramMap.isEmpty()) {
  62. Set<String> keySet = paramMap.keySet();
  63. for (String key : keySet) {
  64. sb.append(sb.toString().contains("?") ? "&" : "?");
  65. sb.append(key).append("=").append(paramMap.get(key));
  66. }
  67. url = sb.toString();
  68. }
  69. return basicGet(url, headers);
  70. }
  71.  
  72. // GET-json
  73. public static String getJsonWithHeader(String url, Map<String, String> headerMap) throws IOException {
  74. Request.Builder request = new Request.Builder().url(url).get().header("Accept", MIME_JSON);
  75. if (headerMap != null) {
  76. headerMap.forEach(request::header);
  77. }
  78. try (Response response = httpClient.newCall(request.build()).execute()) {
  79. log.info("response_code:{}, response_body:{}", response.code(), response.body().string());
  80. return response.body().string();
  81. }
  82. }
  83.  
  84.  
  85. // POST-json传参
  86. public static String postJsonWithHeader(String url, Object reqBody, Map<String, String> headers) throws IOException {
  87. Request.Builder request = new Request.Builder()
  88. .url(url)
  89. .header("Accept", MIME_JSON)
  90. .post(FormBody.create(MediaType.parse(MIME_JSON), JSONObject.toJSONString(reqBody)));
  91. // 遍历并添加 header
  92. if (headers != null) {
  93. headers.forEach(request::header);
  94. }
  95.  
  96. try (Response response = httpClient.newCall(request.build()).execute()) {
  97. log.info("response_code:{}, response_body:{}", response.code(), response.body().string());
  98. return response.body().string();
  99. }
  100. }
  101.  
  102. // POST-param传参
  103. public static String postParamWithHeader(String url, Map<String, Object> paramMap, Map<String, String> headers) throws IOException {
  104. FormBody.Builder formBody = new FormBody.Builder();
  105. if (Objects.nonNull(paramMap)) {
  106. paramMap.forEach((k, v) -> formBody.add(k, (String) v));
  107. }
  108.  
  109. Request.Builder request = new Request.Builder()
  110. .url(url)
  111. .header("Accept", MIME_JSON)
  112. .post(formBody.build());
  113.  
  114. // 遍历并添加 header
  115. if (headers != null) {
  116. headers.forEach(request::header);
  117. }
  118.  
  119. try (Response response = httpClient.newCall(request.build()).execute()) {
  120. log.info("response_code:{}, response_body:{}", response.code(), response.body().string());
  121. return response.body().string();
  122. }
  123. }
  124.  
  125. public static final String octet_stream_str = "application/octet-stream";
  126. public static final MediaType octet_stream = MediaType.parse(octet_stream_str);
  127.  
  128. public static void putStream(String url, InputStream inputStream, long contentLength) {
  129. Response response;
  130. try {
  131. RequestBody requestBody2 = new HttpRequestBody(inputStream, contentLength);
  132.  
  133. Request request = new Request.Builder().url(url)
  134. .addHeader("Content-Type", octet_stream_str)
  135. .put(requestBody2)
  136. .build();
  137. response = httpClient.newCall(request).execute();
  138.  
  139. String result = response.body().string();
  140. if (response.code() != 200) {
  141. throw new Exception("Saturn SDK stream upload failed, url:" + url + "response.code():" + response.code() + ", msg:" + result);
  142. }
  143. } catch (Exception e) {
  144. e.printStackTrace();
  145. } finally {
  146. closeQuietly(inputStream);
  147. }
  148. }
  149.  
  150.  
  151. public static String putFile(String url, File file) throws Exception {
  152. RequestBody requestBody = RequestBody.create(octet_stream, file);
  153. Request request = new Request.Builder().url(url)
  154. .addHeader("Content-Type", octet_stream_str)
  155. .put(requestBody).build();
  156.  
  157. Response response = httpClient.newCall(request).execute();
  158. String result = response.body().string();
  159. int code = response.code();
  160. log.info("putFile end, url:{}, response.code:{}, result:{}", url, code, result);
  161. if (code != 200) {
  162. throw new Exception("putFile failed, response.code():" + code + ", result:" + result);
  163. }
  164. return result;
  165. }
  166.  
  167.  
  168. private static String basicGet(String url, Map<String, String> headers) throws IOException {
  169. Request.Builder builder = new Request.Builder()
  170. .url(url)
  171. .get();
  172. // 遍历并添加 header
  173. if (headers != null) {
  174. headers.forEach(builder::header);
  175. }
  176.  
  177. try (Response response = httpClient.newCall(builder.build()).execute()) {
  178. return response.body().string();
  179. }
  180. }
  181.  
  182. private static String basicDelete(String url, Headers headers) throws IOException {
  183. Request.Builder builder = new Request.Builder().url(url).delete();
  184. if (headers != null) {
  185. builder.headers(headers);
  186. }
  187. try (Response response = httpClient.newCall(builder.build()).execute()) {
  188. return response.body().string();
  189. }
  190. }
  191.  
  192. public static void closeQuietly(Closeable is) {
  193. if (is != null) {
  194. try {
  195. is.close();
  196. } catch (Exception ex) {
  197. log.error("Resources encounter an exception when closing,ex:{}", ex.getMessage());
  198. }
  199. }
  200. }
  201. }
 
bash

这个 OkHttpUtils 类封装了 OkHttpClient 来进行 HTTP 请求,支持 GET、POST、PUT 等常见的 HTTP 方法,并提供了对参数、请求头、文件上传等功能的支持。以下是它的主要功能和使用方法的解释:

  1. OkHttpClient 实例

    • 使用 OkHttpClient.Builder() 创建,设置了超时时间(连接超时 3 秒,读写超时 5 秒),并添加了拦截器。

  2. 静态方法

    • getJsongetgetWithHeadesgetJsonWithHeader:用于 GET 请求,支持无参、有参数和请求头的场景。

    • postJsonWithHeaderpostParamWithHeader:用于 POST 请求,支持 JSON 数据或表单数据传递。

    • putStreamputFile:用于 PUT 请求,支持流和文件上传。

    • basicGetbasicDelete:内部通用方法,分别处理 GET 和 DELETE 请求。

 

三、拓展和使用建议

  • 增强错误处理:当前仅在拦截器中简单处理了异常,可以考虑在各个方法中增加详细的异常处理机制。
  • 连接池管理:默认情况下,OkHttp 使用连接池来提升性能,类内部也可以进一步定制连接池策略来优化并发性能。
  • 异步支持:所有请求均为同步请求,适合使用时可以考虑用 OkHttp 提供的 enqueue() 方法进行异步操作,防止阻塞主线程。

通过这些封装,OkHttpUtils 能够方便地发送 HTTP 请求并处理响应。在实际项目中,你可以根据需要调整超时设置、缓存机制等配置。

 

posted @ 2026-02-08 00:39  charyGao  阅读(98)  评论(0)    收藏  举报