1. 网络基础:HTTP协议原理、请求方法、状态码详解、HTTPS与网络安全
说实话,做Android开发这么多年,我见过太多人一上来就甩Retrofit、OkHttp,结果出了问题连日志都看不懂。网络请求这东西,说白了就是客户端跟服务器之间的一场对话。你连对话的规矩都不懂,出了问题当然一头雾水。
今天咱们就把这块地基打扎实。我保证,看完这一章,你再看那些网络报错,心里会踏实很多。
1.1 HTTP协议原理——你每天都在用,但你真的懂吗?
HTTP,全称是超文本传输协议。名字听着高大上,其实本质就一句话:客户端发请求,服务器给响应。
我刚开始做项目时,总觉得协议这东西是后端该操心的。直到有一次,我负责的App上线后,用户反馈图片加载特别慢。我查了半天,发现是服务器返回的响应头里没有设置缓存策略,导致每次都要重新下载。嗯,从那以后我就明白了——不懂HTTP,你连性能优化都无从下手。
HTTP的工作流程其实很简单,就四步:
- 建立连接:客户端(你的App)跟服务器建立TCP连接
- 发送请求:客户端说“我要这个资源”
- 服务器处理:服务器找到资源,或者告诉你找不到
- 返回响应:服务器把结果打包发回来
你想想看,这个过程跟你去餐厅点餐是不是一模一样?你坐下(建立连接),点菜(发送请求),厨师做菜(服务器处理),服务员上菜(返回响应)。
核心要点:HTTP是无状态的协议。什么叫无状态?就是服务器不记得你是谁。每次请求都是独立的,就像你每次去餐厅,服务员都不记得你上次点了什么。这也是为什么后来有了Cookie和Session这些东西来帮忙“记住”用户。
1.2 请求方法——GET、POST、PUT、DELETE,别用混了
HTTP定义了多种请求方法,但咱们Android开发中,最常用的就这四种。我个人习惯把它们分成两类:查改增删。
| 方法 | 含义 | 幂等性 | 请求体 | 典型场景 |
|---|---|---|---|---|
| GET | 获取资源 | 是 | 无 | 获取用户列表、加载文章 |
| POST | 创建资源 | 否 | 有 | 注册用户、提交订单 |
| PUT | 更新资源(全量) | 是 | 有 | 修改用户全部信息 |
| DELETE | 删除资源 | 是 | 通常无 | 删除某条评论 |
这里有个坑,我必须要说。很多新手会把GET请求的参数直接拼在URL里,像这样:
https://api.example.com/users?id=123&name=张三
这样做有什么问题?第一,URL长度有限制,参数多了会截断。第二,敏感信息直接暴露在URL里,浏览器历史记录、服务器日志都会留下痕迹。我见过有人把密码直接拼在GET请求的URL里……嗯,这就不多说了。
我的建议:查询类的用GET,修改数据类的用POST。如果拿不准,用POST准没错。虽然RESTful规范要求严格区分,但在实际项目中,很多团队为了省事,所有写操作都用POST。我个人觉得,只要团队内部约定好,怎么用都行。
1.3 状态码详解——看懂服务器在说什么
服务器返回的状态码,就是它给你的“暗号”。我刚开始看这些数字时,觉得记不住。后来发现,其实根本不用全记,记住几个关键的就行。
状态码分五类,我按类别给你捋一遍:
1xx:信息类
这类状态码很少见。表示服务器收到了请求,正在处理。你基本不用管它。
2xx:成功类
- 200 OK:请求成功。这是最常见的,看到它就放心了。
- 201 Created:创建成功。POST请求创建资源时,服务器通常会返回这个。
- 204 No Content:请求成功,但没内容返回。DELETE请求经常返回这个。
3xx:重定向类
表示资源位置变了,客户端需要重新请求。Android开发中,如果你用OkHttp,它默认会帮你处理重定向。但如果你用HttpURLConnection,就得自己处理了。
- 301 Moved Permanently:永久重定向。资源彻底搬家了。
- 302 Found:临时重定向。资源暂时挪了个地方。
注意:我曾经遇到过一个坑,服务器返回了302重定向,但OkHttp自动跟随了重定向,结果跳转到了登录页面。用户明明已经登录了,却莫名其妙被踢出了。后来发现是Cookie没带对。所以,遇到3xx状态码,一定要检查一下你的Cookie和Token有没有正确传递。
4xx:客户端错误类
这类状态码最常见,也最让人头疼。说白了,就是客户端(你的App)发错了请求。
- 400 Bad Request:请求格式不对。参数少了、类型错了,都有可能。
- 401 Unauthorized:没登录,或者Token过期了。
- 403 Forbidden:登录了,但没权限。比如普通用户想删管理员发的帖子。
- 404 Not Found:资源不存在。URL写错了,或者数据被删了。
- 405 Method Not Allowed:请求方法不对。比如接口只支持POST,你用了GET。
- 429 Too Many Requests:请求太频繁,被限流了。
5xx:服务器错误类
这类状态码表示服务器出问题了。你基本做不了什么,只能等服务器恢复。
- 500 Internal Server Error:服务器内部错误。后端代码崩了。
- 502 Bad Gateway:网关错误。通常是负载均衡或者代理出了问题。
- 503 Service Unavailable:服务暂时不可用。服务器在维护,或者过载了。
避坑指南:我曾经在项目中遇到一个诡异的问题,用户反馈App偶尔会闪退。查了半天,发现是服务器返回了502,但我们的网络库没有处理这个状态码,直接抛了个异常。从那以后,我要求团队必须对所有5xx状态码做统一处理,至少给用户弹个“服务器繁忙,请稍后再试”的提示。
1.4 HTTPS与网络安全——别让你的数据裸奔
HTTP是明文传输的。什么意思?就是你发的请求、服务器返回的数据,在网络传输过程中,任何人都能截获并看到内容。你想想看,如果你在登录页面输入了密码,结果密码在网络上裸奔……这画面太美我不敢看。
HTTPS就是HTTP的安全版本。它在HTTP和TCP之间加了一层SSL/TLS加密。说白了,就是给你的数据穿了一件防弹衣。
HTTPS的工作原理,我简单说一下:
- 客户端发起请求:你的App说“我要建立安全连接”
- 服务器返回证书:服务器把自己的数字证书发给客户端
- 客户端验证证书:检查证书是否有效、是否被篡改
- 协商加密密钥:双方商量一个只有彼此知道的密钥
- 加密通信:之后的所有数据都用这个密钥加密传输
这里有个关键点——证书验证。Android开发中,如果你用OkHttp,它默认会验证服务器的证书。但有些开发者在测试时,为了省事,会写一个信任所有证书的代码:
// 千万别这么干!
val client = OkHttpClient.Builder()
.hostnameVerifier { _, _ -> true }
.sslSocketFactory(createTrustAllSocketFactory(), createTrustAllTrustManager())
.build()
严重警告:上面这段代码,我见过不止一次出现在生产环境的代码里。这样做等于把HTTPS的加密功能完全废掉了。你的App跟服务器之间的通信,跟裸奔没什么区别。我曾经在一个金融类App的代码评审中发现了这个问题,当时就要求必须改掉。记住,永远不要在正式环境中信任所有证书。
那正确的做法是什么?
- 使用系统默认的证书验证:OkHttp默认就是安全的,别乱改
- 证书固定(Certificate Pinning):如果你对安全性要求极高,可以把服务器的证书指纹硬编码到App里,防止中间人攻击
- 使用HTTPS而不是HTTP:这个不用我说了吧?
我的经验:在Android开发中,网络请求的安全性不仅仅是HTTPS的事。你还要注意:不要在日志里打印敏感信息(密码、Token)、不要在本地明文存储Token、使用安全的加密算法。我见过有人把用户的登录密码直接打印在Logcat里……嗯,这种代码一旦被反编译,后果不堪设想。
好了,这一章的内容就到这里。网络基础这块,说白了就是理解客户端和服务器之间的对话规则。你掌握了HTTP的原理、请求方法、状态码和HTTPS,后面再学Retrofit、OkHttp这些框架,就会觉得豁然开朗。
下一章,咱们聊聊Android中网络请求的几种方式,从HttpURLConnection到OkHttp,再到Retrofit,我会告诉你每个方案的优缺点,以及在实际项目中该怎么选。