Java发送HTTP请求的几种方式
对于一个文章开发者来说,牢固扎实的基础是十分重要的,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 {
HttpResponse<String> response = 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依赖。
<!-- Maven -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>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设计非常简洁流畅。
<!-- Maven -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>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
今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
AI工具与豆包协作优化全攻略
- 上一篇
- AI工具与豆包协作优化全攻略
- 下一篇
- 响应式导航栏制作教程:CSS多设备适配指南
-
- 文章 · java教程 | 1小时前 | interrupt() 优雅关闭 中断状态 Java线程中断 协作式中断
- Java线程安全中断与状态管理方法
- 161浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java8方法引用教程与实例解析
- 258浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java接口与实现分离方法解析
- 490浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- H2与Oracle冲突解决全攻略
- 427浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java转Map方法实用教程
- 394浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java处理UnsupportedOperationException异常技巧
- 249浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Linux部署K8s和Java容器教程
- 269浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java避免类重复的实用技巧
- 404浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java并发synchronized线程安全详解
- 464浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- List与Set区别详解及选择方法
- 492浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- 递归归并排序与多路合并实践解析
- 244浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- Maven依赖冲突解决与版本升级技巧
- 180浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3204次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3416次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3446次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4555次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3824次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览

