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免费学习笔记(深入)”;

这是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.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略显复杂,但它的稳定性和功能丰富度是经过时间考验的。
采用HttpClient向服务器端action请求数据,当然调用服务器端方法获取数据并不止这一种。WebService也可以为我们提供所需数据,那么什么是webService呢?,它是一种基于SAOP协议的远程调用标准,通过webservice可以将不同操作系统平台,不同语言,不同技术整合到一起。 实现Android与服务器端数据交互,我们在PC机器java客户端中,需要一些库,比如XFire,Axis2,CXF等等来支持访问WebService,但是这些库并不适合我们资源有限的android手机客户端,
0
最后是 OkHttp。这个库在Android开发社区里非常流行,但它在后端服务中也越来越受欢迎。OkHttp的设计理念是高效和简洁。它默认支持HTTP/2,有非常优秀的连接池管理,并且提供了拦截器(Interceptor)机制,这让你可以非常方便地对请求和响应进行修改、日志记录、认证添加等操作。它的API非常简洁直观,用起来很舒服。如果你的项目追求性能、简洁的API设计,并且乐于引入一个高质量的第三方库,OkHttp是一个非常棒的选择。我个人在一些微服务项目里,因为它的简洁和高效,也倾向于使用它。
总结一下,如果你的项目是Java 11+,并且对依赖有洁癖,java.net.http.HttpClient是首选。如果需要处理非常复杂的企业级HTTP场景,或者项目Java版本较低,Apache HttpClient依然是可靠的伙伴。而如果追求简洁高效,尤其是在Android或某些微服务场景,OkHttp会让你爱不释手。
在实际开发中,处理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是整个请求的超时,包括连接和读取。RequestConfig 来设置,比如 RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(10000).build()。OkHttpClient.newBuilder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build()。第二个大坑是 错误处理和HTTP状态码。很多人拿到响应后,只看有没有数据,不关心状态码。但HTTP状态码(2xx、3xx、4xx、5xx)是服务器告诉你的“语言”,它说明了请求的成功与否,以及失败的原因。比如404是资源未找到,500是服务器内部错误。不处理这些,你的程序可能会在不应该继续执行的时候继续,导致逻辑错误。
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"))。EntityUtils.toString(entity, "UTF-8")。response.body().string() 默认会尝试从响应头中解析编码,如果没有则使用UTF-8。第四个是 资源泄露。当你打开一个输入流(InputStream)或输出流(OutputStream),或者一个HttpURLConnection、CloseableHttpClient时,用完了一定要关闭它们。否则,连接资源会一直占用,导致系统资源耗尽,最终程序崩溃。
try-with-resources 语句。这是Java 7之后引入的语法糖,可以确保实现了 AutoCloseable 接口的资源在 try 块结束后自动关闭,即使发生异常也一样。HttpClient、Apache CloseableHttpClient、OkHttp Response)都推荐或要求使用 try-with-resources 来管理它们的资源。// 以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通信中非常常见的需求。
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();HttpGet request = new HttpGet("https://example.com/api/data");
request.addHeader("User-Agent", "MyApacheHttpClient/1.0");
request.addHeader("Content-Type", "application/json");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认证。
Authorization头部的值。String auth = "username:password";
String encodedAuth = java.util.Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
// 在请求头中添加
// .header("Authorization", "Basic " + encodedAuth)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")获取新URLRequestConfig 来配置。RequestConfig requestConfig
以上就是如何在Java中发送HTTP请求 Java实现HTTP通信的方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号