关于 unirest-java-4
面向 Java 开发者的 Unirest-Java 4.x 使用参考,涵盖 HTTP 请求、响应处理、流式通信、配置与测试。适用于 Java 11 及以上版本。
主要功能
- 01流畅式 HTTP 请求
- 02使用 GSON 或 Jackson 映射 JSON
- 03通过 CompletableFuture 异步请求
- 04支持 SSE 和 WebSocket
- 05HTTP 响应缓存
- 06模拟 HTTP 客户端测试
适用场景
- 01在 Java 中调用 REST API
- 02通过 HTTP 上传或下载文件
- 03消费服务器发送事件
- 04在单元测试中模拟 HTTP 调用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ full-stack-skills/ java-skills --skill unirest-java-4安装后在 Claude Code 中输入/unirest-java-4确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/caching.mdconfiguration.mdmocking.mdproxies.mdrequests.mdresponses.mdsse.mdupgrade-guide.mdwebsocket.md详细介绍
Unirest-Java 4.x 参考(v4.10.0)
本技能涵盖适用于 Java 11+ 的 Unirest-Java 4.x HTTP 客户端库。它使用内置的 java.net.http.HttpClient(取代 3.x 中的 Apache HttpClient),并默认使用 HTTP/2。
能力范围
✅ 擅长领域
- 使用流畅 API 构建 HTTP 请求(GET、POST、PUT、DELETE、PATCH)
- 使用 GSON 或 Jackson 进行 JSON/对象映射(必须显式声明模块)
- 使用 CompletableFuture 发送异步请求(内置于 java.net.http.HttpClient)
- 上传文件并监控进度
- 通过
Unirest.sse(url)接收 Server-Sent Events(SSE) - 通过
Unirest.webSocket(url)建立 WebSocket 连接 - 对 HTTP 客户端进行模拟测试
- 配置响应缓存的淘汰策略
- 代理配置(简单代理、系统代理、ProxySelector)
- 默认使用 HTTP/2(可通过
config.version()配置) - 通过
config.executor()支持自定义执行器 - 支持 Java Authenticator
⚠️ 要求
- Java 11 或更高版本(使用
java.net.http.HttpClient) - 必须声明 JSON 模块(
unirest-modules-gson或unirest-modules-jackson)以进行对象映射 - 使用 BOM 管理 Maven/Gradle 依赖
❌ 不支持的范围(替代方案)
- 每个请求单独配置代理 → 使用全局
Unirest.config().proxy()(已在 4.x 中移除) - 自定义 HostnameVerifier → 使用
disableHostNameVerification()系统属性 - 独立于连接超时的套接字超时 → 改用
requestTimeout() - 调整连接池参数(
concurrency(total, perRoute))→ 不支持(由 java.net.http 管理) - 套接字错误时自动重试 → 仅对 429/529 使用
retryAfter() - 关闭钩子 → 无需配置(没有需要管理的后台线程)
- 集成 Apache HttpClient → 如需 Apache 专属功能,请使用 3.x
何时使用本技能
当用户需要以下操作时,请使用本技能:
- 在 Java 中向 REST API 发送 HTTP 请求
- 通过 HTTP 上传或下载文件
- 接收 Server-Sent Event 流
- 在单元测试中模拟 HTTP 调用
- 配置 HTTP 请求的代理
- 缓存 HTTP 响应
- 从 Unirest 3.x 迁移到 4.x
快速入门
Maven 依赖(Unirest 4.10.0):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java-bom</artifactId>
<version>4.10.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java-core</artifactId>
</dependency>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-modules-gson</artifactId>
</dependency>
</dependencies>
最简 GET 请求:
String body = Unirest.get("https://api.example.com/users")
.asString()
.getBody();
最简 JSON POST 请求:
HttpResponse<JsonNode> response = Unirest.post("https://api.example.com/users")
.header("Content-Type", "application/json")
.body(new User("Alice", "[email protected]"))
.asJson();
重要:安装
Unirest 4 采用模块化设计。必须声明:
unirest-java-core— HTTP 客户端引擎- JSON 模块 —
unirest-modules-gson或unirest-modules-jackson(对象映射/JSON 解析必需)
⚠️ 如果没有 JSON 模块,调用
asObject()、asJson()和 JSON Patch 将在运行时失败。
完整安装详情请参阅 references/configuration.md。
重要:配置
所有配置均通过 Unirest.config() 完成:
Unirest.config()
.connectTimeout(5000)
.setDefaultHeader("Accept", "application/json")
.setDefaultBasicAuth("user", "pass")
.followRedirects(true)
.verifySsl(true)
.enableCookieManagement(true)
.proxy("proxy.com", 8080, "user", "pass");
主要配置选项:
| 方法 | 影响 | 默认值 |
|---|---|---|
connectTimeout(int) | 连接超时(ms) | 10000 |
requestTimeout(int) | 请求超时 | infinite |
followRedirects(boolean) | 跟随 HTTP 重定向 | true |
verifySsl(boolean) | 强制执行 SSL 验证 | true |
enableCookieManagement(boolean) | 接受/存储 Cookie | true |
retryAfter(boolean) | 对 429/529 自动重试 | false |
defaultBaseUrl(String) | 所有请求的默认基础 URL | none |
多套配置:
// Primary instance (same as static Unirest)
UnirestInstance unirest = Unirest.primaryInstance();
// Spawn a new independent instance
UnirestInstance custom = Unirest.spawnInstance();
custom.config().connectTimeout(3000);
⚠️ 如果创建新实例,关闭该实例的责任由你承担。
完整配置表、拦截器、对象映射器和指标请参阅 references/configuration.md。
重要:发送请求
基本请求类型:
Unirest.get("http://localhost/users").asString();
Unirest.post("http://localhost/users").body(json).asJson();
Unirest.put("http://localhost/users/1").body(user).asEmpty();
Unirest.delete("http://localhost/users/1").asEmpty();
路由参数:
Unirest.get("http://localhost/users/{id}")
.routeParam("id", "42")
.asString();
// Results in http://localhost/users/42
查询参数:
Unirest.get("http://localhost/search")
.queryString("q", "unirest")
.queryString("page", 1)
.asString();
请求头和身份验证:
Unirest.get("http://localhost/protected")
.header("X-Custom", "value")
.basicAuth("user", "pass")
.asString();
表单数据:
Unirest.post("http://localhost/form")
.field("name", "Alice")
.field("age", 30)
.asEmpty();
文件上传:
Unirest.post("http://localhost/upload")
.field("file", new File("/path/to/file.zip"))
.asEmpty();
异步请求:
CompletableFuture<HttpResponse<JsonNode>> future = Unirest.get("http://localhost/data")
.asJsonAsync(response -> {
System.out.println(response.getBody());
});
JSON Patch(RFC-6902):
Unirest.jsonPatch("http://localhost/resource")
.add("/fruits/-", "Apple")
.remove("/bugs")
.replace("/name", "Updated")
.asJson();
有关上传进度、分页请求、客户端证书等内容,请参阅 references/requests.md。
重要:处理响应
响应类型:
// String
String body = Unirest.get(url).asString().getBody();
// Object mapping
Book book = Unirest.get(url).asObject(Book.class).getBody();
// Generic types
List<Book> books = Unirest.get(url)
.asObject(new GenericType<List<Book>>(){}).getBody();
// JSON
JsonNode json = Unirest.get(url).asJson().getBody();
// File
File file = Unirest.get(url).asFile("/tmp/download.zip").getBody();
// Empty (status/headers only)
HttpResponse resp = Unirest.delete(url).asEmpty();
错误处理:
Unirest.get("http://localhost/data")
.asJson()
.ifSuccess(response -> handleSuccess(response))
.ifFailure(response -> {
log.error("Status: " + response.getStatus());
response.getParsingError().ifPresent(e -> {
log.error("Parse error: " + e.getMessage());
});
});
解析错误:
response.getParsingError().ifPresent(ex -> {
String originalBody = ex.getOriginalBody();
String message = ex.getMessage();
});
映射错误对象:
HttpResponse<Book> book = Unirest.get(url).asObject(Book.class);
Error err = book.mapError(Error.class);
有关下载进度、大型响应、响应体映射等内容,请参阅 references/responses.md。
重要:服务器发送事件(SSE)
异步消费 SSE:
var future = Unirest.sse("https://stream.example.com/events")
.connect(event -> {
var data = event.asObject(MyEvent.class);
System.out.println("Event: " + data.getTitle());
});
同步消费 SSE:
Unirest.sse("https://stream.example.com/events")
.connect()
.map(event -> event.asObject(MyEvent.class))
.forEach(data -> System.out.println("Event: " + data.getTitle()));
⚠️ SSE 连接会一直保持。生产系统中请使用异步模式。 ⚠️ 对象映射需要配置 ObjectMapper。
完整详情请参阅 references/sse.md。
重要:缓存
基本缓存:
Unirest.config().cacheResponses(true);
使用选项进行高级缓存:
Unirest.config().cacheResponses(Cache.builder()
.depth(100) // Max entries
.maxAge(5, TimeUnit.MINUTES)); // Entry TTL
自定义缓存(例如 Guava):
Unirest.config().cacheResponses(
Cache.builder().backingCache(new MyGuavaCache()));
有关自定义缓存实现的详情,请参阅 references/caching.md。
重要:模拟
静态模拟:
MockClient mock = MockClient.register();
mock.expect(HttpMethod.GET, "http://api.example.com/users")
.thenReturn("{\"name\":\"Alice\"}")
.withStatus(200);
String body = Unirest.get("http://api.example.com/users")
.asString().getBody();
// body == "{\"name\":\"Alice\"}"
mock.verifyAll(); // Verify all expects were called
实例模拟:
UnirestInstance unirest = Unirest.spawnInstance();
MockClient mock = MockClient.register(unirest);
请求体匹配:
mock.expect(HttpMethod.POST, "http://api.example.com/users")
.body(FieldMatcher.of("name", "Alice", "role", "admin"))
.thenReturn()
.withStatus(201);
按调用次数验证:
var expect = mock.expect(HttpMethod.GET, "http://api.example.com/users").thenReturn();
expect.verify(); // At least once
expect.verify(Times.never()); // Never called
有关 POJO 响应、多个 expect 等内容,请参阅 references/mocking.md。
重要:代理
简单代理:
Unirest.config().proxy("proxy.com", 8080, "user", "pass");
系统属性:
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "7777");
Unirest.config().useSystemProperties(true);
多个代理(ProxySelector):
Unirest.config()
.proxy(new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
if (uri.getHost().equals("internal.com")) {
return List.of(new Proxy(HTTP,
InetSocketAddress.createUnresolved("internal-proxy.com", 8080)));
}
return List.of(new Proxy(HTTP,
InetSocketAddress.createUnresolved("default-proxy.com", 8080)));
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {}
});
有关 Authenticator 设置和详情,请参阅 references/proxies.md。
重要:WebSocket
连接到 WebSocket:
Unirest.webSocket("ws://localhost/socket")
.connect(ws -> {
ws.sendText("Hello!");
ws.onMessage(message -> {
System.out.println("Received: " + message);
});
});
使用 POJO 映射的 WebSocket:
Unirest.webSocket("ws://localhost/events")
.connect(ws -> {
ws.onMessage(event -> {
MyEvent data = event.asObject(MyEvent.class);
processEvent(data);
});
});
⚠️ WebSocket 仅支持 4.x,不适用于 3.x。
完整详情请参阅 references/websocket.md。
快速修复
| 错误 | 原因 | 修复方法 |
|---|---|---|
NoClassDefFoundError: JsonObject | 缺少 JSON 模块 | 添加 unirest-modules-gson 或 unirest-modules-jackson 依赖 |
java.lang.NoClassDefFoundError: kong/unirest/Unirest | 4.x 中的包名错误 | 将导入从 kong.unirest.* 改为 kong.unirest.core.* |
asObject() 返回的响应体为 null | 响应解析失败 | 检查 response.getParsingError() 获取详情 |
ConnectException: Connection timed out | 服务器无法访问或超时时间过短 | 增大 connectTimeout 或检查网络 |
SSLHandshakeException | SSL 验证失败 | 仅在开发环境中使用 verifySsl(false),并在生产环境中修复证书 |
Host header override not allowed | Java 11+ HttpClient 限制 | 设置系统属性 jdk.httpclient.allowRestrictedHeaders=host |
| 4.x 中代理无法使用 | 4.x 默认禁用系统属性 | 显式调用 useSystemProperties(true) |
注意事项
- 必须使用 Java 11+ — Unirest 4.x 使用
java.net.http.HttpClient,无法在 Java 8 上运行 - 必须声明 JSON 模块 — 与 3.x 不同,4.x 没有默认 JSON 解析器。若未使用
unirest-modules-gson或unirest-modules-jackson,JSON 解析将在运行时失败 - 包名重命名 —
kong.unirest(3.x)→kong.unirest.core(4.x),JSON 模块位于kong.unirest.modules.gson/jackson(4.3+) - 默认使用 HTTP/2 — 4.x 默认使用
HttpClient.Version.HTTP_2。使用config.version(HttpClient.Version.HTTP_1_1)可降级 - 不支持单请求代理 — 3.x 允许使用
request.proxy(host, port)。4.x 仅支持通过Unirest.config().proxy()设置全局代理 - 没有 socketTimeout — 3.x 有独立的
socketTimeout()。4.x 使用requestTimeout(),涵盖整个请求生命周期 - 不支持并发调优 —
concurrency(total, perRoute)是 Apache 专属功能。java.net.http 在内部管理连接池 - 不支持自动重试 —
automaticRetries(true)是 Apache 专属功能。4.x 仅对 429/529 响应提供retryAfter() - 没有 HostnameVerifier — 3.x 有
hostnameVerifier(verifier)。4.x 使用disableHostNameVerification()系统属性(作用于整个 JVM) - 默认禁用系统代理属性 — 与 3.x(默认为 true)不同,4.x 的
useSystemProperties默认为false - SSE 和 WebSocket 仅支持 4.x — 3.x 中不存在
Unirest.sse()和Unirest.webSocket() - 简化了 Mock 注册 — 3.x:
MockClient.register()要求调用.httpClient(client).asyncClient(client)。4.x:只需调用.httpClient(client) - 配置更改需要重置 — Unirest 激活后,更改客户端创建配置前必须先调用
config().reset() - 已移除
isRunning()— 3.x 有Unirest.isRunning()。4.x 已将其移除(没有需要监控的后台线程)
参考资料
请求
- requests.md — 路由参数、查询参数、请求头、身份验证、正文类型、文件上传、上传进度、异步请求、分页请求、客户端证书
响应
- responses.md — asEmpty/asString/asObject/asJson/asFile、GenericType、解析错误、错误对象映射、下载进度、大型响应、错误处理
配置
- configuration.md — 完整配置选项表、全局拦截器、多种配置、对象映射器(Jackson/GSON)、指标
Mock
- mocking.md — 静态/实例 Mock、多个期望(评分)、验证、正文匹配、表单参数、POJO 响应
缓存
- caching.md — 基础/高级缓存、自定义缓存实现
服务器推送事件
- sse.md — SSE 异步/同步消费、对象映射要求
WebSocket
- websocket.md — WebSocket 连接、消息处理、POJO 映射
代理
- proxies.md — 简单代理、系统属性、带 Authenticator 的 ProxySelector
升级指南
- upgrade-guide.md — 从 3.x 迁移到 4.x、包名重命名、Maven 坐标变更、行为差异