当前位置: 首页 > news >正文

从零开始学Java:第31章 网络和 HTTP:让 Java 程序和外部服务通信

第31章 网络和 HTTP:让 Java 程序和外部服务通信

到目前为止,你写的程序主要在本机运行:读命令行、写文件、处理内存对象。真实应用经常要和外部系统通信。

比如:

  • 查询天气。
  • 调用短信服务。
  • 请求后端接口。
  • 下载文件。
  • 把订单提交给支付系统。
  • Android App 调用服务器接口。

这些都离不开网络和 HTTP。

这一章先不做复杂 Web 服务器,而是从客户端角度理解 HTTP:Java 程序如何发送请求,如何接收响应,如何处理状态码、JSON、超时和异常。

一、客户端和服务器

网络通信里常见两类角色:

客户端:发起请求的一方。 服务器:接收请求并返回响应的一方。

浏览器访问网站:

浏览器 -> 服务器 服务器 -> HTML/CSS/JS

Java 程序调用接口:

Java程序 -> API服务器 API服务器 -> JSON

Android App 调后端:

Android App -> 后端服务 后端服务 -> JSON数据

HTTP 是最常见的应用层协议。

二、HTTP 请求和响应

一次 HTTP 通信可以理解为:

请求 Request 响应 Response

请求包含:

  • URL。
  • 方法。
  • 请求头。
  • 请求体。

响应包含:

  • 状态码。
  • 响应头。
  • 响应体。

例如:

GET /books/001 HTTP/1.1 Host: api.example.com Accept: application/json

响应:

HTTP/1.1 200 OK Content-Type: application/json {"isbn":"001","title":"Java入门"}

三、URL 的组成

https://api.example.com:443/books/001?detail=true

拆开:

部分含义
https协议
api.example.com主机名
443端口
/books/001路径
detail=true查询参数

常见端口:

  • HTTP 默认 80。
  • HTTPS 默认 443。

实际开发中,接口文档会告诉你 URL、方法、参数和响应格式。

四、HTTP 方法

常见方法:

方法常见含义
GET查询
POST新增或提交
PUT整体更新
PATCH部分更新
DELETE删除

例子:

GET /books GET /books/001 POST /books PUT /books/001 DELETE /books/001

这不是 Java 语法,而是接口设计约定。

五、状态码

常见状态码:

状态码含义
200成功
201创建成功
400请求参数错误
401未登录
403无权限
404资源不存在
409冲突,比如重复创建
500服务器内部错误

调用接口时不能只看有没有响应体。要先看状态码。

200:正常处理响应。 400/404:通常是请求方问题。 500:服务器问题。

六、Java HttpClient

Java 11 开始,标准库提供HttpClient

发送 GET 请求:

importjava.net.URI;importjava.net.http.HttpClient;importjava.net.http.HttpRequest;importjava.net.http.HttpResponse;importjava.time.Duration;publicclassGetDemo{publicstaticvoidmain(String[]args)throwsException{HttpClientclient=HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();HttpRequestrequest=HttpRequest.newBuilder().uri(URI.create("https://api.example.com/books/001")).timeout(Duration.ofSeconds(10)).header("Accept","application/json").GET().build();HttpResponse<String>response=client.send(request,HttpResponse.BodyHandlers.ofString());System.out.println(response.statusCode());System.out.println(response.body());}}

这里有三个对象:

  • HttpClient:负责发送请求。
  • HttpRequest:表示请求。
  • HttpResponse<String>:表示响应,body 是字符串。

七、处理状态码

不要直接使用 body。

intstatus=response.statusCode();if(status>=200&&status<300){System.out.println("成功:"+response.body());}elseif(status==404){System.out.println("资源不存在");}else{System.out.println("请求失败,状态码:"+status+",响应:"+response.body());}

可以封装:

publicstaticStringrequireSuccess(HttpResponse<String>response){intstatus=response.statusCode();if(status>=200&&status<300){returnresponse.body();}thrownewIllegalStateException("HTTP请求失败,状态码:"+status+",响应:"+response.body());}

这样业务代码不会到处重复判断。

八、发送 POST JSON

请求体是 JSON:

{"isbn":"001","title":"Java入门"}

Java 代码:

Stringjson="{\"isbn\":\"001\",\"title\":\"Java入门\"}";HttpRequestrequest=HttpRequest.newBuilder().uri(URI.create("https://api.example.com/books")).timeout(Duration.ofSeconds(10)).header("Content-Type","application/json").header("Accept","application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build();HttpResponse<String>response=client.send(request,HttpResponse.BodyHandlers.ofString());

Content-Type表示你发出去的数据格式。

Accept表示你希望服务器返回什么格式。

真实项目里 JSON 不应该手写字符串,应该用 Jackson:

ObjectMappermapper=newObjectMapper();Stringjson=mapper.writeValueAsString(bookRequest);

九、把响应 JSON 转成对象

假设响应:

{"isbn":"001","title":"Java入门","author":"作者A"}

定义 DTO:

publicclassBookResponse{privateStringisbn;privateStringtitle;privateStringauthor;publicStringgetIsbn(){returnisbn;}publicvoidsetIsbn(Stringisbn){this.isbn=isbn;}publicStringgetTitle(){returntitle;}publicvoidsetTitle(Stringtitle){this.title=title;}publicStringgetAuthor(){returnauthor;}publicvoidsetAuthor(Stringauthor){this.author=author;}}

解析:

ObjectMappermapper=newObjectMapper();BookResponsebook=mapper.readValue(response.body(),BookResponse.class);

DTO 是 Data Transfer Object,数据传输对象。

它和你的领域模型Book可以相同,也可以不同。接口返回什么,DTO 就按接口格式设计。

十、超时很重要

网络请求不能无限等。

连接超时:

HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();

请求超时:

HttpRequest.newBuilder().timeout(Duration.ofSeconds(10))

如果不设置超时,接口卡住时,你的程序可能长时间无响应。

命令行程序会卡住。

服务器程序会占住线程。

Android App 会影响用户体验。

十一、同步请求和异步请求

同步:

HttpResponse<String>response=client.send(request,HttpResponse.BodyHandlers.ofString());

当前线程会等待响应。

异步:

client.sendAsync(request,HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body).thenAccept(System.out::println);

异步请求返回CompletableFuture

初学阶段先掌握同步请求。异步请求和并发、线程池关系更复杂,后面可以继续深入。

十二、下载文件

把响应保存到文件:

HttpRequestrequest=HttpRequest.newBuilder().uri(URI.create("https://example.com/file.zip")).build();HttpResponse<Path>response=client.send(request,HttpResponse.BodyHandlers.ofFile(Path.of("data","file.zip")));System.out.println(response.statusCode());System.out.println(response.body());

BodyHandlers.ofFile会把响应体写到文件。

如果文件很大,不要先读成字符串。

十三、一个简单 API 客户端类

把请求封装起来:

publicclassBookApiClient{privatefinalHttpClientclient;privatefinalURIbaseUri;privatefinalObjectMappermapper;publicBookApiClient(StringbaseUrl){this.client=HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();this.baseUri=URI.create(baseUrl);this.mapper=newObjectMapper();}publicBookResponsefindBook(Stringisbn){try{URIuri=baseUri.resolve("/books/"+isbn);HttpRequestrequest=HttpRequest.newBuilder().uri(uri).timeout(Duration.ofSeconds(10)).header("Accept","application/json").GET().build();HttpResponse<String>response=client.send(request,HttpResponse.BodyHandlers.ofString());Stringbody=requireSuccess(response);returnmapper.readValue(body,BookResponse.class);}catch(IOExceptione){thrownewIllegalStateException("调用图书接口失败",e);}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewIllegalStateException("调用图书接口被中断",e);}}privateStringrequireSuccess(HttpResponse<String>response){intstatus=response.statusCode();if(status>=200&&status<300){returnresponse.body();}thrownewIllegalStateException("HTTP状态码异常:"+status+",响应:"+response.body());}}

这段代码有几个要点:

  • 网络 IO 可能失败,要处理IOException
  • 线程可能被中断,要恢复中断标记。
  • HTTP 状态码不是 2xx 时,不当成成功。
  • JSON 解析失败也会抛异常。

十四、不要把 HTTP 代码散在业务里

不推荐:

publicvoidborrowBook(Stringisbn,StringreaderId){HttpClientclient=HttpClient.newHttpClient();// 这里调用远程图书接口// 然后继续借书}

更好的分层:

BookApiClient:负责 HTTP LibraryService:负责借书业务

业务层调用客户端:

BookResponsebook=bookApiClient.findBook(isbn);

HTTP 细节集中在一个类里,方便测试和替换。

十五、常见错误

1. 只看 body,不看状态码

404、500 也可能有 body,但不是成功。

2. 不设置超时

网络请求可能一直卡住。

3. JSON 手写拼接

简单演示可以,真实项目用 Jackson。

4. InterruptedException 后不恢复中断

推荐:

catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewIllegalStateException("请求被中断",e);}

5. 把 HTTP 调用散落到各个业务方法

应该封装成 API Client。

十六、练习

  1. HttpClient发送一个 GET 请求,打印状态码和 body。
  2. requireSuccess方法,非 2xx 抛异常。
  3. 构造一个 POST JSON 请求。
  4. 用 Jackson 把对象转 JSON。
  5. 写一个BookApiClient,封装findBook(isbn)
  6. 给请求设置连接超时和请求超时。
  7. 思考:HTTP 接口失败时,业务层应该重试、提示用户,还是直接失败?

十七、本章小结

你现在应该理解:

  • HTTP 是请求响应模型。
  • 请求包含 URL、方法、header、body。
  • 响应包含状态码、header、body。
  • GET 常用于查询,POST 常用于提交。
  • 状态码必须检查。
  • Java 11 的HttpClient可以发送 HTTP 请求。
  • JSON 应使用 Jackson 等库解析。
  • 网络请求必须考虑超时、IO 异常和中断。
  • HTTP 代码应该封装在 API Client 中,不要散落在业务层。

下一章讲数据库和 JDBC。HTTP 是程序和远程服务通信,JDBC 是程序和数据库通信。它们都会遇到外部资源、异常、连接管理和数据格式问题。

http://www.jsqmd.com/news/1092855/

相关文章:

  • FFmpeg视频切片与AES-128加密完整实战指南
  • 从零构建 AI 客服系统:Next.js 14 + RAG + 向量检索实战
  • 【HarmonyOS/OpenHarmony】创新体验:从应用入口到页面加载理解全场景应用基础链路
  • 如何用AI写代码 ? AI编程提示词怎么写 ?AI写的代码如何调试
  • U校园自动答题工具:如何2分钟搞定网课必修题的终极指南
  • 从弗朗西斯·奇切斯特的环球航行看:技术、勇气与人类精神的现代启示
  • ClamAV病毒库自动更新与异常告警:Linux服务器安全运维实战
  • 全平台Chrome配置SSLKEYLOGFILE与Wireshark解密HTTPS流量实战指南
  • Steam成就自由掌控:告别无法完成的游戏挑战
  • 小白也能懂的备份防勒索实战(一):不懂技术也要做备份?我试了十几种方案,最终选了它
  • 基于 Ragas 与通义千问实现 RAG 系统答案正确性自动评估
  • 基于鸿蒙十二阶均衡体系:境外全域隐性渗透的安全风险与均衡治理路径——基于全域均衡数理模型推演(十三)
  • 2026在线去除本地视频水印工具推荐!免费无水印导出、安全无需下载电脑端
  • 每日更新!免费股票日k、分时k线数据,etf分钟数据,截至到2026-07月最新数据,含全沪京深7000+股票
  • YgoMaster终极指南:如何免费搭建游戏王大师决斗离线服务器
  • 新手也能上手!2026年实测靠谱的专业降AI率平台
  • 智能微博文案助手项目介绍
  • 从“方阵的行列式”说起:一次对数学严谨性的追问
  • 5分钟高效激活Windows与Office:实用智能激活完整指南
  • MicroPython BLE HID开发指南:打造无线键盘、鼠标和游戏手柄
  • iTrustee Client安全认证机制:CA认证与TEE通信的7个安全层级详解
  • 【深度解析】GPT-5.6 Sol/Tara/Luna能力边界、安全风险与Python选型评估实
  • Ubuntu SSH 强制密钥登录:配置不生效的排查与修复
  • 北京IT培训机构有哪些:深度解析北京IT职业教育市场现状
  • 酷狗KGM文件怎么转MP3?推荐几种实用转换工具
  • 亿元合家欢动画《悟空大圣》正式定档7月24日暑期上映
  • 2024年德化钙钛矿太阳能路灯选购指南:3招帮你挑对好产品
  • 2026 降AIGC工具实测盘点:值得体验,毕业党生存手册
  • 【云原生与DevOps】03-K8s生产环境部署Checklist:你踩过这18个坑吗
  • 秦兵马俑博物馆小程序-springboot+app