25_Java 网络与HTTP客户端
TCP 与 HTTP 边界、JDK HTTP Client、超时、重试和 SSRF 防护。
Java 网络与 HTTP 客户端
学习目标:区分 TCP、HTTP 与应用层契约,并在 Java 服务中安全调用外部 API。
1. 从连接到请求
TCP 提供有序字节流,不自带“一个请求对应一条消息”的业务边界;HTTP 在其上定义方法、路径、头和响应状态。超时至少要考虑连接建立与整个请求处理,重试还要考虑请求是否有副作用。DNS、TLS、代理和连接池都是生产调用链的一部分。
2. JDK HTTP Client 最小示例
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 Main {
public static void main(String[] args) throws Exception {
try (HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(3)).build()) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/health"))
.timeout(Duration.ofSeconds(5))
.GET().build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
}
}
}
示例中的地址只是占位;运行前改为你控制的测试服务。Java 21 中 HttpClient 可关闭;若项目运行在更早 JDK,需按该版本 API 调整。状态码非 2xx 不一定抛异常,必须显式检查。响应体还需限制大小并验证结构,不能把外部 JSON 直接当可信领域对象。
3. 重试与故障隔离
GET 在满足服务端语义时通常适合有界重试;POST 若已经执行但响应丢失,盲目重试可能创建重复数据。对写入接口先设计幂等键。重试设置最大次数、退避和总时间预算;错误率高时无限重试会放大故障。请求日志记录目标服务、耗时和安全的错误类别,不记录令牌或完整敏感响应。
4. 安全边界与实验
如果 URL 来自用户输入,直接请求可能造成 SSRF,让服务访问内网或云元数据地址。使用服务端允许列表、受控 DNS/网络策略与重定向规则,不要只检查字符串前缀。
练习:调用本机测试服务分别模拟 200、500、慢响应与连接失败,记录每种结果的超时和重试决策。