java.net.HttpURLConnection (JDK 内置)
这是 Java 标准库自带的方式,无需添加任何依赖,但它比较底层,用起来相对繁琐,不推荐在新项目中使用,但了解其基本原理是有益的。
特点:
- 优点:JDK 内置,无需引入外部库。
- 缺点:API 繁琐,功能有限(如连接池、异步支持等),处理 JSON/XML 等数据需要手动转换。
示例:GET 请求
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) {
String urlString = "https://jsonplaceholder.typicode.com/posts/1";
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("GET");
// 设置请求头
connection.setRequestProperty("Accept", "application/json");
// 获取响应码
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: " + response.toString());
} else {
System.out.println("GET request failed");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Apache HttpClient (功能强大,工业级标准)
这是 Apache 基金会提供的 HTTP 客户端库,功能非常强大,支持连接池、重试、异步请求等,是许多大型项目和企业级应用的首选。
特点:
- 优点:功能全面,稳定可靠,性能优秀(尤其是连接池),社区活跃。
- 缺点:需要引入第三方依赖。
Maven 依赖
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 如果需要处理 JSON,可以添加 Jackson 或 Gson 依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version> <!-- 请使用最新版本 -->
</dependency>
示例:GET 和 POST 请求
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.StringEntity;
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.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.net.URIBuilder;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class ApacheHttpClientExample {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
public static void main(String[] args) {
// 1. GET 请求示例
System.out.println("--- GET Request ---");
getPosts();
// 2. POST 请求示例
System.out.println("\n--- POST Request ---");
createPost();
}
public static void getPosts() {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 构建带查询参数的 URL
URI uri = new URIBuilder(BASE_URL + "/posts")
.addParameter("userId", "1")
.build();
HttpGet request = new HttpGet(uri);
request.addHeader("Accept", "application/json");
try (CloseableHttpResponse response = httpClient.execute(request)) {
System.out.println("Response Code: " + response.getCode());
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
System.out.println("Response Body: " + result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void createPost() {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(BASE_URL + "/posts");
// 设置请求头
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Accept", "application/json");
// 设置请求体 (JSON)
String jsonPayload = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
StringEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
System.out.println("Response Code: " + response.getCode());
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
String result = EntityUtils.toString(responseEntity);
System.out.println("Response Body: " + result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
OkHttp (现代、高效、易于使用)
OkHttp 是目前非常流行的 HTTP 客户端库,由 Square 公司(现已移交 OpenJS 基金会)开发,它以其简洁的 API、出色的性能(自动处理 GZIP、缓存、连接池)和对现代网络协议(HTTP/2, SPDY)的支持而闻名。
特点:
- 优点:API 设计简洁易用,性能卓越,支持同步和异步请求,是 Android 开发的推荐库。
- 缺点:需要引入第三方依赖。
Maven 依赖
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 如果需要处理 JSON,可以添加 Jackson 或 Gson 依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version> <!-- 请使用最新版本 -->
</dependency>
示例:GET 和 POST 请求
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class OkHttpExample {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
private static final OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) {
// 1. GET 请求示例
System.out.println("--- GET Request ---");
getPost();
// 2. POST 请求示例
System.out.println("\n--- POST Request ---");
createPost();
}
public static void getPost() {
Request request = new Request.Builder()
.url(BASE_URL + "/posts/1")
.header("Accept", "application/json")
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 获取响应体
String responseBody = response.body().string();
System.out.println("Response Code: " + response.code());
System.out.println("Response Body: " + responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void createPost() {
// 构建请求体 (JSON)
Post post = new Post();
post.setTitle("foo");
post.setBody("bar");
post.setUserId(1);
try {
String jsonPayload = objectMapper.writeValueAsString(post);
RequestBody body = RequestBody.create(
jsonPayload,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url(BASE_URL + "/posts")
.post(body)
.header("Content-Type", "application/json")
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
String responseBody = response.body().string();
System.out.println("Response Code: " + response.code());
System.out.println("Response Body: " + responseBody);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 用于 JSON 序列化的简单 POJO 类
static class Post {
private String title;
private String body;
private int userId;
// Getters and Setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
}
}
Spring RestTemplate (Spring 生态专用)
如果你的项目是基于 Spring 或 Spring Boot 的,那么使用 RestTemplate 或 WebClient 是最佳选择。RestTemplate 是一个同步的 HTTP 客户端,在 Spring 生态中非常方便,因为它可以自动将 JSON 转换为 Java 对象(反序列化)。
特点:
- 优点:与 Spring 框架无缝集成,支持自动 JSON 序列化/反序列化,模板方法调用简单。
- 缺点:仅适用于 Spring 项目,在 Spring Boot 3.0 中已标记为不推荐,推荐使用
WebClient。
Maven 依赖 (Spring Boot 项目中通常已包含)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
示例:GET 和 POST 请求
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.Collections;
public class RestTemplateExample {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
private static final RestTemplate restTemplate = new RestTemplate();
public static void main(String[] args) {
// 1. GET 请求示例
System.out.println("--- GET Request ---");
getPost();
// 2. POST 请求示例
System.out.println("\n--- POST Request ---");
createPost();
}
public static void getPost() {
String url = BASE_URL + "/posts/1";
// 直接指定返回类型,RestTemplate 会自动处理 JSON 到 Post 对象的转换
Post post = restTemplate.getForObject(url, Post.class);
System.out.println("Retrieved Post: " + post);
}
public static void createPost() {
String url = BASE_URL + "/posts";
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
// 创建请求体 (Java 对象)
Post newPost = new Post();
newPost.setTitle("foo");
newPost.setBody("bar");
newPost.setUserId(1);
// 构建 HttpEntity
HttpEntity<Post> request = new HttpEntity<>(newPost, headers);
// 发送 POST 请求并指定返回类型
Post createdPost = restTemplate.postForObject(url, request, Post.class);
System.out.println("Created Post: " + createdPost);
}
// 用于 JSON 序列化的简单 POJO 类
static class Post {
private int id;
private String title;
private String body;
private int userId;
// Getters and Setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
@Override
public String toString() {
return "Post{" +
"id=" + id +
", title='" + title + '\'' +
", body='" + body + '\'' +
", userId=" + userId +
'}';
}
}
}
Spring WebClient (响应式,未来趋势)
WebClient 是 Spring 5 引入的响应式、非阻塞 HTTP 客户端,是 RestTemplate 的现代替代品,它基于 Project Reactor,非常适合构建高性能、高并发的应用。
特点:
- 优点:非阻塞,性能更高,支持流式处理,是 Spring 5+ 和 Spring Boot 3+ 的推荐客户端。
- 缺点:学习曲线较陡峭,需要理解响应式编程(Mono, Flux)。
示例:GET 和 POST 请求
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
public class WebClientExample {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
private static final WebClient webClient = WebClient.create(BASE_URL);
public static void main(String[] args) {
// 1. GET 请求示例
System.out.println("--- GET Request ---");
getPost();
// 2. POST 请求示例
System.out.println("\n--- POST Request ---");
createPost();
}
public static void getPost() {
Mono<Post> postMono = webClient.get()
.uri("/posts/1")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Post.class);
// 阻塞式获取结果(在 main 方法中为了演示,实际异步应用中应使用 subscribe)
Post post = postMono.block();
System.out.println("Retrieved Post: " + post);
}
public static void createPost() {
Post newPost = new Post();
newPost.setTitle("foo");
newPost.setBody("bar");
newPost.setUserId(1);
Mono<Post> createdPostMono = webClient.post()
.uri("/posts")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.bodyValue(newPost) // 直接传入 Java 对象
.retrieve()
.bodyToMono(Post.class);
Post createdPost = createdPostMono.block();
System.out.println("Created Post: " + createdPost);
}
// 用于 JSON 序列化的简单 POJO 类
static class Post {
private int id;
private String title;
private String body;
private int userId;
// Getters and Setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
@Override
public String toString() {
return "Post{" +
"id=" + id +
", title='" + title + '\'' +
", body='" + body + '\'' +
", userId=" + userId +
'}';
}
}
}
总结与如何选择
| 库名称 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| HttpURLConnection | JDK 内置,无依赖 | API 繁琐,功能弱 | 简单脚本、无外部依赖的极小项目 |
| Apache HttpClient | 功能强大,稳定,工业级 | 依赖较多,API 相对复杂 | 企业级 Java 应用,需要高级特性的后端服务 |
| OkHttp | API 简洁,性能高,流行 | 需要引入依赖 | 新项目,特别是移动端(Android)和需要高性能的 Java 应用 |
| RestTemplate | Spring 生态集成好,使用方便 | 仅限 Spring,已被标记不推荐 | 所有 Spring/Spring Boot 项目(但建议迁移到 WebClient) |
| WebClient | 非阻塞,高性能,响应式 | 学习曲线陡峭,需要理解响应式编程 | 新的 Spring 5+/Spring Boot 3+ 项目,特别是高并发、微服务架构 |
选择建议:
- 新项目,非 Spring 环境:优先选择 OkHttp,它在易用性和性能之间取得了很好的平衡。
- 新项目,Spring/Spring Boot 环境:直接选择 WebClient,它是未来的方向。
- 维护旧项目,使用 Spring:继续使用 RestTemplate 即可,除非有性能或新功能需求再考虑迁移。
- 企业级、复杂系统:Apache HttpClient 是一个非常成熟和可靠的选择。
- 快速原型或无依赖需求:可以使用
HttpURLConnection,但实际开发中不推荐。
