Java发送HTTP请求的几种方式
时间:2025-07-20 08:33:34 142浏览 收藏
知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个文章开发实战,手把手教大家学习《Java发送HTTP请求的几种方法》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!
Java中发送HTTP请求的主流方式有四种,分别是:1. 使用 java.net.HttpURLConnection(适用于简单请求或无法引入第三方库的项目);2. 使用 Java 11 引入的 java.net.http.HttpClient(推荐用于Java 11及以上版本,支持HTTP/2和异步请求);3. 使用 Apache HttpClient(功能强大,适合复杂企业级场景);4. 使用 OkHttp(高效简洁,适合Android或微服务项目)。每种方式各有优劣,选择取决于项目需求、Java版本及开发偏好。
在Java中发送HTTP请求,核心在于选择合适的API或库来构建、发送请求并处理响应。这并不是一个单一的“最佳”方案,更多的是根据项目需求、Java版本以及个人偏好来权衡。你可以使用Java自带的HttpURLConnection
(虽然有点老旧但依然可用),Java 11引入的HttpClient
(现代且功能强大),或者Apache HttpClient、OkHttp这类业界广泛使用的第三方库。选择哪种,往往决定了你代码的简洁性、可维护性和功能丰富度。

解决方案
要在Java中实现HTTP通信,我通常会根据项目所用的Java版本和对功能复杂度的需求来决定。
1. 使用 java.net.HttpURLConnection
(Java SE 1.1 及更高版本)

这是Java内置的API,无需额外依赖。它功能完备,但用起来确实有点啰嗦,尤其是在处理复杂的请求头、参数或响应体时。我个人觉得,如果只是发个简单的GET请求,或者项目环境限制不能引入第三方库,它还能勉强用用。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpUrlConnectionExample { public static void main(String[] args) { try { URL url = new URL("https://jsonplaceholder.typicode.com/posts/1"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); // 5秒连接超时 connection.setReadTimeout(5000); // 5秒读取超时 int responseCode = connection.getResponseCode(); System.out.println("GET Response Code :: " + responseCode); if (responseCode == HttpURLConnection.HTTP_OK) { // success BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); System.out.println(response.toString()); } else { System.out.println("GET request not worked"); } } catch (Exception e) { e.printStackTrace(); } } }
2. 使用 java.net.http.HttpClient
(Java 11 及更高版本)

Java 11引入的HttpClient
是现代Java HTTP客户端的首选。它支持HTTP/2、WebSocket,并且提供了同步和异步两种API。用起来比HttpURLConnection
舒服太多了,链式调用让代码可读性大大提升。如果你的项目能用Java 11及以上版本,我强烈推荐这个。
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; public class JavaHttpClientExample { public static void main(String[] args) { HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .followRedirects(HttpClient.Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(5)) .build(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1")) .GET() // 默认就是GET,也可以不写 .build(); try { HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Response Body: " + response.body()); // 异步请求示例 client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(body -> System.out.println("Async Body: " + body)) .join(); // 等待异步完成,实际应用中通常不阻塞 } catch (Exception e) { e.printStackTrace(); } } }
3. 使用 Apache HttpClient (第三方库)
Apache HttpClient是Java世界里非常成熟且功能强大的HTTP客户端库,它提供了丰富的特性,比如连接池、认证、代理、重试机制等。对于需要处理复杂HTTP场景的企业级应用来说,它依然是一个非常可靠的选择。需要引入Maven或Gradle依赖。
org.apache.httpcomponents httpclient 4.5.13
import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class ApacheHttpClientExample { public static void main(String[] args) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1"); // 可以添加请求头 request.addHeader("User-Agent", "Apache HttpClient Demo"); try (CloseableHttpResponse response = httpClient.execute(request)) { System.out.println("Status Code: " + response.getStatusLine().getStatusCode()); HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("Response Body: " + EntityUtils.toString(entity)); } } } catch (Exception e) { e.printStackTrace(); } } }
4. 使用 OkHttp (第三方库)
OkHttp是Square公司开源的一个高效HTTP客户端,在Android开发中尤为流行,但在后端服务中也常被使用。它支持HTTP/2、连接池、响应缓存等,API设计非常简洁流畅。
com.squareup.okhttp3 okhttp 4.9.3
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import java.io.IOException; public class OkHttpExample { public static void main(String[] args) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://jsonplaceholder.typicode.com/posts/1") .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } System.out.println("Status Code: " + response.code()); System.out.println("Response Body: " + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } }
Java中HTTP请求的几种主流实现方式有哪些?
谈到Java里发HTTP请求,选择确实不少,各有各的特点和适用场景。我个人在不同的项目里都用过,也踩过一些坑,所以对它们的优劣多少有些体会。
首先是 java.net.HttpURLConnection
。这玩意儿是Java标准库自带的,你不需要引入任何第三方依赖就能用。它的好处是“开箱即用”,对于一些简单的GET或POST请求,比如请求一个静态资源或者提交一个简单的表单,它完全够用。但它的API设计确实比较老旧,用起来很“命令式”,代码会显得比较冗长,尤其是在你需要设置很多请求头、处理重定向、或者管理连接池的时候,你会发现它力不从心,写起来很费劲。在我看来,它更适合那些对依赖有严格限制的老项目,或者只是想快速验证一个HTTP请求的场景。
接着是 java.net.http.HttpClient
,这是Java 11之后的新宠。我得说,Sun/Oracle终于在这方面做了些现代化改进。它的API设计非常符合现代编程习惯,支持链式调用,而且原生支持HTTP/2和WebSocket,这是很大的优势。它既能同步阻塞地发请求,也能异步非阻塞地发,这对于构建响应式服务非常有用。如果你正在开发基于Java 11或更高版本的新项目,或者有机会升级现有项目的Java版本,我强烈建议优先考虑它。它自带连接池管理,性能也相当不错,而且不用引入第三方依赖,很“干净”。
然后是 Apache HttpClient。这几乎是Java企业级应用中HTTP客户端的“老牌劲旅”了。在HttpClient
出现之前,Apache HttpClient几乎是处理复杂HTTP请求的不二之选。它提供了非常丰富的功能,比如强大的连接池管理、多种认证机制、代理支持、请求重试策略等等。如果你需要对HTTP请求有非常精细的控制,或者你的应用场景非常复杂(比如需要处理大量的并发请求、复杂的认证流程),那么Apache HttpClient依然是一个非常稳健的选择。虽然它需要引入外部依赖,API也相对Java 11的HttpClient
略显复杂,但它的稳定性和功能丰富度是经过时间考验的。
最后是 OkHttp。这个库在Android开发社区里非常流行,但它在后端服务中也越来越受欢迎。OkHttp的设计理念是高效和简洁。它默认支持HTTP/2,有非常优秀的连接池管理,并且提供了拦截器(Interceptor)机制,这让你可以非常方便地对请求和响应进行修改、日志记录、认证添加等操作。它的API非常简洁直观,用起来很舒服。如果你的项目追求性能、简洁的API设计,并且乐于引入一个高质量的第三方库,OkHttp是一个非常棒的选择。我个人在一些微服务项目里,因为它的简洁和高效,也倾向于使用它。
总结一下,如果你的项目是Java 11+,并且对依赖有洁癖,java.net.http.HttpClient
是首选。如果需要处理非常复杂的企业级HTTP场景,或者项目Java版本较低,Apache HttpClient依然是可靠的伙伴。而如果追求简洁高效,尤其是在Android或某些微服务场景,OkHttp会让你爱不释手。
处理HTTP响应时常见的坑与解决方案?
在实际开发中,处理HTTP响应远不是拿到字符串那么简单。我踩过不少坑,也总结了一些经验,这里分享几个常见的“雷区”和我的处理方式。
一个最常见的坑是 超时问题。网络请求不是总能立刻得到响应的,如果服务器响应慢或者网络不稳定,你的程序可能会一直等下去,导致线程阻塞,甚至整个服务崩溃。我常遇到的是连接超时(Connect Timeout)和读取超时(Read Timeout)。连接超时是指客户端尝试与服务器建立连接的时间限制,如果超过这个时间还没连上,就放弃。读取超时是指连接建立后,客户端等待服务器发送数据的时间限制,如果数据传输中断或太慢,也会超时。
- 解决方案: 务必设置合理的超时时间。
HttpURLConnection
:connection.setConnectTimeout(milliseconds)
和connection.setReadTimeout(milliseconds)
。HttpClient
(Java 11+):HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5))
和HttpRequest.newBuilder().timeout(Duration.ofSeconds(10))
。注意,HttpRequest
上的timeout是整个请求的超时,包括连接和读取。- Apache HttpClient: 可以通过
RequestConfig
来设置,比如RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(10000).build()
。 - OkHttp:
OkHttpClient.newBuilder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build()
。
第二个大坑是 错误处理和HTTP状态码。很多人拿到响应后,只看有没有数据,不关心状态码。但HTTP状态码(2xx、3xx、4xx、5xx)是服务器告诉你的“语言”,它说明了请求的成功与否,以及失败的原因。比如404是资源未找到,500是服务器内部错误。不处理这些,你的程序可能会在不应该继续执行的时候继续,导致逻辑错误。
- 解决方案: 总是检查响应状态码。
- 对于2xx(成功),继续处理响应体。
- 对于4xx(客户端错误)或5xx(服务器错误),应该抛出自定义异常或记录日志,并根据业务逻辑决定如何回滚或重试。我通常会封装一个方法,如果状态码不是2xx,就抛出
HttpClientErrorException
或HttpServerErrorException
这样的异常。
第三个是 编码问题。HTTP响应体可能是UTF-8、GBK或者其他编码。如果你的程序没有正确地以服务器声明的编码去读取响应流,就会出现乱码。这在处理中文内容时尤其常见。
- 解决方案: 优先使用响应头中
Content-Type
字段声明的编码。如果没有明确声明,或者声明不一致,UTF-8通常是安全的默认选择。HttpURLConnection
:new InputStreamReader(connection.getInputStream(), "UTF-8")
。HttpClient
(Java 11+):HttpResponse.BodyHandlers.ofString(Charset.forName("UTF-8"))
。- Apache HttpClient:
EntityUtils.toString(entity, "UTF-8")
。 - OkHttp:
response.body().string()
默认会尝试从响应头中解析编码,如果没有则使用UTF-8。
第四个是 资源泄露。当你打开一个输入流(InputStream
)或输出流(OutputStream
),或者一个HttpURLConnection
、CloseableHttpClient
时,用完了一定要关闭它们。否则,连接资源会一直占用,导致系统资源耗尽,最终程序崩溃。
- 解决方案: 使用
try-with-resources
语句。这是Java 7之后引入的语法糖,可以确保实现了AutoCloseable
接口的资源在try
块结束后自动关闭,即使发生异常也一样。- 所有现代HTTP客户端库(如Java 11
HttpClient
、ApacheCloseableHttpClient
、OkHttpResponse
)都推荐或要求使用try-with-resources
来管理它们的资源。
- 所有现代HTTP客户端库(如Java 11
// 以Apache HttpClient为例,展示try-with-resources try (CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = httpClient.execute(request)) { // 处理响应 System.out.println("Status Code: " + response.getStatusLine().getStatusCode()); HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("Response Body: " + EntityUtils.toString(entity)); } } catch (IOException e) { e.printStackTrace(); }
这些坑,说起来简单,但实际写代码时一不留神就可能掉进去。养成良好的编程习惯,比如总是设置超时、检查状态码、正确处理编码和关闭资源,能省去你调试时的大量麻烦。
如何在HTTP请求中加入认证、头部信息或处理重定向?
在构建HTTP请求时,很多时候你需要更精细的控制,比如添加自定义头部、进行身份认证,或者处理服务器的重定向。这都是HTTP通信中非常常见的需求。
1. 添加头部信息 (Headers)
HTTP头部是客户端和服务器之间传递元数据的方式。比如User-Agent
(标识客户端类型)、Content-Type
(请求体类型)、Accept
(期望的响应类型)、Authorization
(认证凭证)等等。
HttpURLConnection
: 相对繁琐,需要调用connection.setRequestProperty("Header-Name", "Header-Value")
。connection.setRequestProperty("User-Agent", "MyJavaApp/1.0"); connection.setRequestProperty("Content-Type", "application/json");
HttpClient
(Java 11+): 链式调用非常方便。HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com/api/data")) .header("User-Agent", "MyJavaHttpClient/1.0") .header("Content-Type", "application/json") .GET() .build();
- Apache HttpClient: 同样直观。
HttpGet request = new HttpGet("https://example.com/api/data"); request.addHeader("User-Agent", "MyApacheHttpClient/1.0"); request.addHeader("Content-Type", "application/json");
- OkHttp:
Request.Builder
提供了header()
和addHeader()
方法。Request request = new Request.Builder() .url("https://example.com/api/data") .header("User-Agent", "MyOkHttp/1.0") .addHeader("Content-Type", "application/json") // addHeader可以添加多个同名header .build();
2. 加入认证 (Authentication)
常见的认证方式有Basic认证和Bearer Token认证。
- Basic认证: 这种方式是将用户名和密码用冒号连接,然后进行Base64编码,作为
Authorization
头部的值。String auth = "username:password"; String encodedAuth = java.util.Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); // 在请求头中添加 // .header("Authorization", "Basic " + encodedAuth)
- Bearer Token认证: 这是OAuth 2.0等现代认证流程中常用的方式,将一个令牌(Token)放在
Authorization
头部,前面加上Bearer
。String token = "your_access_token_here"; // 在请求头中添加 // .header("Authorization", "Bearer " + token)
3. 处理重定向 (Redirects)
当服务器返回3xx状态码时,表示资源已移动或需要客户端重定向到另一个URL。大多数HTTP客户端默认会处理重定向,但有时你需要更精细的控制。
HttpURLConnection
: 默认是跟随重定向的。你可以通过connection.setInstanceFollowRedirects(false)
来禁用自动重定向,然后手动处理。connection.setInstanceFollowRedirects(false); // 禁用自动重定向 // int responseCode = connection.getResponseCode(); // if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM) { // String newUrl = connection.getHeaderField("Location"); // // 然后你就可以用newUrl再发一个请求 // }
HttpClient
(Java 11+):HttpClient.Builder
提供了followRedirects()
方法来控制重定向行为。HttpClient.Redirect.NORMAL
: 默认行为,跟随所有重定向。HttpClient.Redirect.ALWAYS
: 总是跟随重定向,包括POST到GET的重定向。HttpClient.Redirect.NEVER
: 从不跟随重定向。HttpClient client = HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.NEVER) // 禁用自动重定向 .build(); // 如果响应是3xx,你可以从response.headers().firstValue("Location")获取新URL
- Apache HttpClient: 默认是跟随重定向的。可以通过
RequestConfig
来配置。RequestConfig requestConfig
今天关于《Java发送HTTP请求的几种方式》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
359 收藏
-
259 收藏
-
475 收藏
-
164 收藏
-
368 收藏
-
443 收藏
-
164 收藏
-
127 收藏
-
228 收藏
-
301 收藏
-
460 收藏
-
191 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习