Java 发送 HTTP 请求的方式随着 Java 版本和生态的发展,经历了从繁琐到便捷的演变,主要可以分为以下几类:

- JDK 内置原生方式:不依赖任何第三方库。
HttpURLConnection(Java 1.1+) - 传统、繁琐,但无需额外依赖。HttpClient(Java 11+) - 现代、高效、功能强大,是 Java 官方推荐的方式。
- 第三方流行库:提供了更简洁、更强大的 API。
- Apache HttpClient - 长期以来是事实上的标准,功能非常全面。
- OkHttp - 在 Android 和 Java 后端都非常流行,以其高效和易用性著称。
- Spring RestTemplate - Spring 生态中的经典工具,与 Spring 框架无缝集成。
- Spring WebClient - Spring 5 引入的响应式、非阻塞式 HTTP 客户端,是 RestTemplate 的现代化替代品。
下面我们逐一介绍这些方法,并提供代码示例。
JDK 内置方式
a. HttpURLConnection (Java 1.1+)
这是最古老、最基础的方式,它非常繁琐,需要手动处理流、连接状态、编码等,不推荐在新项目中使用,但了解它有助于理解底层原理。
特点:
- 优点:无需任何外部依赖。
- 缺点: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) throws Exception {
String urlString = "https://jsonplaceholder.typicode.com/posts/1";
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("GET");
// 设置请求头
connection.setRequestProperty("User-Agent", "MyJavaApp/1.0");
// 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { // 200
// 读取响应数据
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 Body: " + response.toString());
} else {
System.out.println("GET request failed");
}
}
}
b. HttpClient (Java 11+)
这是 Java 11 引入的现代 HTTP 客户端,旨在取代老旧的 HttpURLConnection,它功能强大、API 设计现代、支持异步和非阻塞请求。
特点:
- 优点:现代、高效、功能全面(异步、WebSocket、HTTP/2)、官方推荐。
- 缺点:需要 Java 11 或更高版本。
示例代码 (同步 GET 请求):
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 JavaHttpClientSyncExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // 可选,优先使用 HTTP/2
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.header("User-Agent", "MyJavaApp/1.0")
.build();
// 发送请求并获取响应 (同步方式)
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
示例代码 (异步 GET 请求):
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class JavaHttpClientAsyncExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build();
// 发送请求并获取响应 (异步方式)
CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// 使用 thenAccept 处理响应结果
futureResponse.thenAccept(response -> {
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
});
// 主线程需要等待,否则程序会立即退出
System.out.println("Request sent, waiting for response...");
futureResponse.join(); // 阻塞直到异步任务完成
}
}
第三方流行库
a. Apache HttpClient
曾长期是 Java HTTP 客户端的王者,功能极其强大和稳定,在企业级应用中广泛使用。
Maven 依赖:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version> <!-- 请使用最新版本 -->
</dependency>
示例代码:
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.io.entity.EntityUtils;
public class ApacheHttpClientExample {
public static void main(String[] args) throws Exception {
// 创建 HttpClient 实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建 HTTP GET 请求
HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");
// 发送请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 打印响应状态码
System.out.println("Status Code: " + response.getCode());
// 获取响应实体并转换为字符串
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("Response Body: " + responseBody);
}
}
}
}
b. OkHttp
由 Square 公司开发,以其高效、简洁的 API 而闻名,是 Android 开发和许多 Java 项目的首选。
Maven 依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- 请使用最新版本 -->
</dependency>
示例代码:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class OkHttpExample {
public static void main(String[] args) throws IOException {
// 创建 OkHttpClient 实例
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());
}
}
}
c. Spring RestTemplate (Spring Framework)
如果你在使用 Spring 框架,RestTemplate 是进行同步 HTTP 调用的传统工具,它非常方便,能与 Spring 的其他特性(如 JSON 自动转换、错误处理)无缝集成。
Maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
注意:spring-boot-starter-web 会自动包含 RestTemplate 的依赖。
示例代码:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RestTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(RestTemplateApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
// 另一个类中调用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyApiService {
@Autowired
private RestTemplate restTemplate;
public String getPost() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
// 直接将响应映射为 Java 对象,非常方便
Post post = restTemplate.getForObject(url, Post.class);
System.out.println("Fetched Post: " + post);
return post != null ? post.toString() : "null";
}
}
// 假设的 Post 类
class Post {
private int userId;
private int id;
private String title;
private String body;
// Getters and Setters
@Override
public String toString() {
return "Post{" +
"userId=" + userId +
", id=" + id +
", title='" + title + '\'' +
", body='" + body + '\'' +
'}';
}
}
d. Spring WebClient (Spring Framework 5+)
WebClient 是 Spring 5 引入的响应式、非阻塞式 HTTP 客户端,是 RestTemplate 的现代化替代品,它基于 Project Reactor,性能更高,特别适合高并发场景。
Maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
示例代码:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class WebClientApplication {
public static void main(String[] args) {
SpringApplication.run(WebClientApplication.class, args);
}
@Bean
public WebClient webClient() {
return WebClient.create();
}
}
// 另一个类中调用
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class MyWebApiService {
@Autowired
private WebClient webClient;
public Mono<Post> getPostAsync() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
return webClient.get()
.uri(url)
.retrieve() // 发出请求并接收响应
.bodyToMono(Post.class); // 将响应体解码为 Post 对象
}
public void callGetPost() {
getPostAsync()
.subscribe(post -> { // 订阅 Mono,处理结果
System.out.println("Fetched Post (Async): " + post);
});
System.out.println("Request sent, but not necessarily received yet.");
// 主线程不能立即退出,否则异步任务可能无法完成
// 在实际应用中,通常是一个持续运行的服务器
try {
Thread.sleep(2000); // 简单等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Post 类同上
总结与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
HttpURLConnection |
无需依赖 | API陈旧,代码繁琐,功能弱 | 学习、极简单脚本、无法引入第三方库的环境 |
HttpClient (Java 11+) |
现代、高效、功能全、官方推荐 | 需要 Java 11+ | 新项目的首选,特别是非 Spring 项目 |
| Apache HttpClient | 功能强大、稳定、企业级成熟 | 依赖较大,API 相对较旧 | 需要高级特性或已在使用它的遗留项目 |
| OkHttp | API简洁、高效、流行 | 依赖第三方库 | Android 应用、对性能和易用性要求高的 Java 项目 |
RestTemplate |
与 Spring 生态集成完美,使用方便 | 已标记为不推荐 (deprecated in Spring 6.0) | 旧版 Spring 项目,或必须使用同步阻塞方式的场景 |
WebClient |
响应式、非阻塞、高性能 | 基于 Reactor,有学习曲线 | 新版 Spring 项目,特别是微服务、高并发场景 |
如何选择?
- 新项目,不使用 Spring 框架:优先选择
HttpClient(Java 11+),它是官方的、现代的,无需额外依赖。 - 新项目,使用 Spring Boot 3.x:优先选择
WebClient,它是未来的方向,性能更好。 - 新项目,使用 Spring Boot 2.x:仍然可以使用
RestTemplate,但建议开始向WebClient迁移。RestTemplate依然稳定可靠。 - Android 开发:OkHttp 是不二之选。
- 维护遗留企业级项目:如果项目已经在用 Apache HttpClient,继续使用它是稳妥的选择。
- 快速原型或学习:
HttpURLConnection可以让你了解底层,但实际开发不推荐。RestTemplate或OkHttp能让你更快地实现功能。
