01 · Web 基础(Web Basics)

📅 预计 45 分钟 | ⭐ = 高频考点 | 📌 中英术语见文末
✍️ 配套练习:网页 quiz shengxia.dev/java?module=01


1.1 Web 是什么与工作原理

像逛菜市场:你问价,摊位给货

把 Web(万维网)想成菜市场:你走到摊位前问"今天有什么菜"(发出请求),摊位老板把菜摆给你看(返回响应)。菜市场能天天开张,靠的是"顾客—摊位"这个稳定分工;Web 能天天运转,靠的是"客户端—服务器"这套固定配合。你每刷一次网页、每点一次链接,本质上都在重复这个"问价—给货"的循环,只是速度快到你几乎感觉不到。

Web 全称是万维网(World Wide Web),它是运行在互联网之上的服务,而不是互联网本身。互联网是连接全世界电脑的物理"路网"(光纤、网线、路由器组成的传输网络),Web 只是跑在这条路上的一种"快递服务"。除了 Web,电子邮件(Email)、文件传输(FTP)、远程登录(SSH)也都是跑在互联网上的服务。理解这一层,你就不会把"上不了网"和"网站打不开"混为一谈:前者是路断了,后者可能是路上这家店关了。

Web 由三个核心部分组成:

组件 英文 作用 生活类比
网页 Web Page 你看到的内容 摊位上的菜
网址 URL 找到内容的地址 摊位的门牌号
浏览器 Browser 帮你取内容的工具 你的腿

Web 的工作原理:一问一答

Web 的所有操作都可以概括为四个字:请求、响应(request / response)。浏览器主动向服务器要东西,服务器被动把东西还回来。这种"主动方永远是浏览器、被动方永远是服务器"的关系不会互换,就像菜市场里永远是顾客开口问价,摊位老板不会追着你推销。

用 Java 伪代码描述这个"问答循环",你会发现核心逻辑其实很简单:

// 伪代码:Web 世界的本质就是一个"问答循环"
while (服务器在运行) {
    请求 req = 接收请求();      // 浏览器说"我要 xxx"
    内容 out = 找答案(req);     // 找现成文件,或让程序现算
    返回响应(out);              // 把网页端到浏览器面前
}

服务器找答案有两种方式:要么直接读磁盘上写死的文件(静态网页),要么运行一段程序现场生成(动态网页)。这两种方式我们在 1.6 节详细对比,你现在只要记住"回答之前必须先收到问题"就够了。

💡 记忆口诀:Web = 一问一答。浏览器永远是"问"的一方,服务器永远是"答"的一方,角色不能互换。

⚠️ 常见错误

  1. 把 Web 和互联网混为一谈:互联网是物理网络,Web 只是跑在它上面的众多服务之一。为什么容易混?因为 90% 的人上网只用浏览器,误以为"联网 = 逛网页"。怎么避免?记住 Email、FTP 也是互联网服务,它们和 Web 是并列关系。
  2. 以为请求只能由浏览器发起:curl 命令、爬虫程序、手机 App、小程序都能发 HTTP 请求,浏览器只是最常用的客户端。为什么重要?调试接口时你经常用 curl 模拟请求,不会这个手段会很被动。
  3. 认为服务器一定是一台电脑:服务器可以是多台机器组成的集群,也可以一台机器上跑多个"虚拟服务器"。"服务器"本质是"提供服务的程序",不是一个具体的铁盒子。面试里问"一台服务器能同时部署几个网站"时,答案就是"无数个,只要端口和域名能区分"。

1.2 客户端-服务器架构

饭店:顾客点菜,后厨做菜

客户端-服务器架构(Client-Server Architecture)就像一家饭店:你(客户端)拿着菜单点菜,后厨(服务器)做完端上来。顾客不关心后厨怎么切菜、用什么锅;后厨也不关心你坐哪一桌、穿什么衣服。两边只通过"菜单—上菜"这个约定好的接口打交道,互不越界。这种"分工明确、接口稳定"的架构,让 Web 能支撑几十亿用户同时使用。

  • 客户端(Client):发起请求的一方,典型代表是浏览器。它负责两件事:把网页渲染成你能看懂的界面,以及把你的操作(点按钮、输表单、划页面)翻译成一个 HTTP 请求。
  • 服务器(Server):保存和处理资源的一方。它 24 小时开机、有固定地址(IP),负责存网页、存图片、跑程序、连数据库。服务器一旦宕机,所有依赖它的客户端都会"点菜没人做"。
维度 客户端 服务器
角色 主动请求 被动响应
典型代表 浏览器、手机 App Tomcat、Nginx、Apache
资源 几乎不保存业务数据 网页、图片、数据库的大本营
状态 想关就关 常年在线,宕机业务就停

客户端负责"显示",服务器负责"算和存"

分工的核心一句话:客户端不保存真正的资源,服务器才是资源的大本营。你刷淘宝,商品图片、库存、价格、你的购物车,全部存在淘宝的服务器和数据库里;你本地的浏览器只保存了一份"看过的副本"(缓存)。所以哪怕你把浏览器缓存清空、换个新电脑、甚至把手机格式化,数据一样不少——只要服务器还在,数据就在。

这也解释了为什么 Web 开发的核心在"服务端":权限校验、数据计算、安全防护都发生在服务器上。客户端做得再漂亮,也只是"一张嘴";服务器才是"食材和手艺"。这就是为什么要花大力气学 Servlet、学数据库、学部署——都是"后厨"的功夫。

💡 记忆口诀:客户端是"前台",服务器是"仓库+后厨"。前台只管递单上菜,仓库后厨才管存货做菜。丢数据先找服务器,别急着怪自己浏览器。

⚠️ 常见错误

  1. 把"换设备数据还在"归功于浏览器:很多人以为"我登录过的网站换个电脑还在"是浏览器厉害。其实数据都在服务器,浏览器只是在你登录后拿了一张"临时通行证"(Cookie)。这个认知错误会让你在后端开发时忘记"状态存哪里"。
  2. 以为服务器必须是一台高性能电脑:初学者总把服务器想象成机房里的高端机器。开发阶段你本机跑一个 Tomcat 就是服务器,性能不重要,重要的是"职责"——它在扮演提供资源的角色。
  3. 忽略客户端可能不诚实:初学者常假设"浏览器发的请求都是真的"。但客户端完全可控,攻击者可以伪造请求、篡改参数。所以服务器必须自己校验数据,绝不能相信客户端传过来的任何值——这是后文安全设计的基本立场。

1.3 URL 结构分解 ⭐

快递单:地址拆成五段

寄快递要写清"省 / 市 / 区 / 街道 / 门牌号",缺一段都可能送错。URL(统一资源定位符)就是 Web 世界的快递单,地址被拆成几段,每一段都有明确含义、缺一不可。看这个标准例子:

https://www.example.com:8080/path/to/page?name=tom&age=20
组成 例子 作用
协议 https 用什么规则访问
主机名 www.example.com 哪台服务器
端口 8080 服务器上的哪个"门"
路径 /path/to/page 哪个资源
查询参数 name=tom&age=20 捎给服务器的附加信息

每一段都要背清楚

  • 协议(protocol):最常见的两个是 httphttps。https 多一个 s,表示"安全版"(在 HTTP 外面套了一层加密)。协议必须和服务器配置匹配,否则连不上。
  • 主机名(host):给人看的域名,本质是"好记的名字"。机器之间真正通信靠 IP 地址,域名只是通过 DNS 翻译成 IP 的别名。
  • 端口(port):一台服务器上可以开很多服务(网页服务、邮件服务、数据库服务),端口就是区分这些服务的"门牌号"。HTTP 默认 80,HTTPS 默认 443;浏览器里不写端口号时,会自动补默认值
  • 路径(path):资源在服务器上的存放位置,如 /index.html/user/login。注意它和服务器磁盘路径不是一回事,是"虚拟路径",由服务器程序决定怎么映射。
  • 查询参数(query)? 后面跟着的键值对,多个用 & 连接,用来捎带附加信息(如搜索关键词、页码)。参数到 # 为止# 后面是网页内部的"锚点"(定位到页面某个位置),根本不会发给服务器。

用 Java 伪代码拆开这个 URL,体会每一段的含义:

// 伪代码:拆 URL 看结构(真实解析更复杂,这里只看各部分含义)
String url = "https://www.example.com:8080/path/to/page?name=tom&age=20";
String protocol = url.substring(0, 8);     // "https://"  用什么规则
String host     = url.substring(8, 25);    // "www.example.com" 去哪台机器
String port     = url.substring(25, 29);   // "8080" 敲哪个门
String path     = url.substring(29, 44);   // "/path/to/page" 要哪个资源
String query    = url.substring(45);       // "name=tom&age=20" 捎带的附加信息
System.out.println("协议=" + protocol);
System.out.println("主机=" + host + " 端口=" + port);
// 输出:协议=https://  主机=www.example.com 端口=8080

💡 记忆口诀:拆 URL 从右往左读——? 分参数、# 是锚点、/ 分段、: 后是端口、// 后是主机、最前是协议。

⚠️ 常见错误

  1. 协议写错导致无法访问:服务器只开了 443 端口时,你用 http:// 访问会连接失败或被强制跳转。为什么?443 端口根本没有明文服务在监听。怎么避免?先确认网站给的是 http 还是 https,再决定地址栏怎么写。
  2. 忘记端口号的作用localhost:8080localhost:80 可能是两个完全不同的服务。初学者经常"在 8080 起的服务却用 80 去访问",结果一直连不上。怎么避免?启动服务时看控制台输出的端口,访问时带上它。
  3. 查询参数分隔符写错:第一个参数前用 ?,后面的用 &。写成 ?name=tom?age=20,第二个 ? 会被当成参数名的一部分,服务器取 age 时得到 null。这是排查"参数丢失"时最先该看的地方。
  4. URL 里出现裸空格:URL 不允许裸空格,空格要编码成 %20name=to m 会解析失败或截断。为什么?空格在 URL 里有特殊含义(分隔符),必须转义。前端开发时用 encodeURIComponent() 处理参数就能避免。

1.4 HTTP 请求-响应模型概览 ⭐

点外卖:下单一句话,收货一张票

HTTP(超文本传输协议)是 Web 的"对话规则",规定了两边怎么开口、怎么接话、怎么结束。点外卖时你下单一句话"一份黄焖鸡,微辣",商家做好后给你一张取餐票;HTTP 世界里,请求(request)和响应(response)就是这两张纸,一张是你说的话,一张是商家的回执。

一个 HTTP 请求的原始报文长这样(第 02 讲会逐行拆解,这里先混个眼熟):

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html

一个 HTTP 响应的原始报文长这样:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

<html><body>你好,Web 世界!</body></html>

核心要点:请求里说明"想要什么(路径)、给谁(Host)、怎么给(方法)";响应里说明"成没成功(状态码)、什么类型(Content-Type)、内容是什么(主体)"。两边都用纯文本沟通,这正是 HTTP 好调试的原因——抓包工具里看到的都是人眼能读懂的字符,而不是乱码。

💡 记忆口诀:HTTP = 一问一答的纯文本对话。请求"提要求",响应"给结果"。看到请求先看方法,看到响应先看状态码。

DNS:分拣中心帮你查门牌号

机器之间通信用的是 IP 地址(如 93.184.216.34),但人类记不住这一串数字,于是有了域名。DNS(域名系统) 就是把这个映射关系管起来的全球"电话簿":你给它一个域名,它告诉你对应的 IP。整个过程在毫秒级完成,你几乎感知不到。

你输入 www.example.com
   ↓ 问:这个域名对应哪个 IP?
DNS 服务器翻电话簿 → 答:93.184.216.34
你的电脑拿着这个 IP 去建立连接

DNS 的一个特点值得记住:它有多级缓存。你的电脑、路由器、本地运营商都缓存了最近查过的记录,所以同一个域名不会每次都问"总电话簿"。这也是为什么改完网站域名解析后要等一段时间才生效——因为沿途缓存的旧记录还没过期。

💡 记忆口诀:DNS = 域名查 IP 的电话簿。浏览器记不住 IP,就像你记不住朋友的手机号,通讯录帮你查,而且沿途各级都有备份。


1.5 一次完整请求的旅程

从"敲回车"到"看到页面"的六步

把一次访问当成寄一封信给远方的朋友:你写下地址(输入网址)、邮局查门牌(DNS 解析)、打车过去(TCP 建立连接)、递上信(发送请求)、朋友回信(服务器响应)、你读信(浏览器渲染)。这六步环环相扣,任何一步断了,页面都出不来。

① 输入网址      在地址栏敲下 https://www.example.com
② DNS 解析      查出 IP:93.184.216.34
③ TCP 连接      三次握手,确认通话就绪
④ 发送请求      浏览器说:我要 GET /index.html
⑤ 服务器处理    返回 200 + 网页内容
⑥ 浏览器渲染    解析 HTML/CSS/JS,画出你看到的页面

每一步都可能出问题:DNS 挂了打不开(②)、服务器宕机连不上(③⑤)、404 是资源不存在(⑤)。排错时顺着这条链一步步排查,是后端开发的基本功:先看能不能解析域名(ping 或 nslookup),再看端口通不通(telnet),最后看服务器日志——这样能快速把问题范围缩小到"网络层还是应用层"。

// 伪代码:服务器处理一次请求的简化流程
void 处理(请求 req, 响应 resp) {
    String 路径 = req.getPath();              // 客户要什么
    if ("/index.html".equals(路径)) {
        resp.setStatus(200);                  // 找到了
        resp.write("网页内容");
    } else if ("/login".equals(路径)) {
        resp.setStatus(200);                  // 动态生成
        resp.write("这是登录页,由程序现场生成");
    } else {
        resp.setStatus(404);                  // 没找到
        resp.write("页面不存在");
    }
}

一问一答,答完就散

一个请求对应一个响应,而且默认"无状态":服务器处理完一个请求就"失忆"了,不记得你上次来要过什么。就像快餐店排队——你上回点了什么,店员这次完全不知道,每次都从头来。这一特性是 HTTP 协议设计的初衷:简单、省资源、扛得住海量并发。

但"无状态"也带来了问题:购物车怎么记住?登录状态怎么保持?答案是 Cookie 和 Session(第 02 讲、后续章节会讲)。你只要先记住这个基本模型:默认无记忆,想要记忆得自己加机制

💡 记忆口诀:一问一答,答完就散。想记住上次的状态?那是 Cookie / Session 的事,基础模型本身"无记忆"。


1.6 静态网页与动态网页 + Web 容器

打印店:现成海报 vs 现做海报

静态网页(static)像打印店货架上的现成海报:印好了放在那,谁来都拿同一张,速度快、成本低。动态网页(dynamic)像定制海报:老板根据你给的信息(名字、日期、照片)现场排版打印,每个人拿到的都可能不同。淘宝的搜索结果页、你的个人订单页,都是动态网页——内容取决于"你是谁、你搜了什么"。

对比 静态网页 动态网页
内容 写死存在文件里 运行时计算 / 查数据库生成
例子 index.html 淘宝商品页、订单页
谁生成 服务器直接返回文件 程序(Java/PHP/Python)现算
优点 快、省资源 内容可变、千人千面
缺点 内容一成不变 慢一些、依赖服务器算力

动态网页的"现场做"靠的是服务器上的程序。要让 Java 程序能处理 HTTP 请求、动态生成 HTML,就需要一个"翻译官 + 管家"——这就是 Web 容器

Web 容器:Servlet 的房东和管家

Web 容器(Web Container),最经典的是 Tomcat,它把"接待客人"的杂活全包了,只留"怎么招待"给你写。具体做三件事:

  1. 监听端口、解析 HTTP:浏览器发来的原始 HTTP 报文它替你拆开,变成一个个 Java 对象,你不用碰字符串。
  2. 管理 Servlet 生命周期:Servlet 是你写的处理请求的 Java 类(第 03 讲),容器负责"什么时候创建、什么时候调用、什么时候销毁"。
  3. 处理并发:多个用户同时访问,容器自动为每个请求分配一个线程,你不用手写线程池。

没有容器时这些活全要你自己干,感受一下:

// 伪代码:没有容器时你要自己干的活
ServerSocket 端口 = new ServerSocket(8080);  // ① 自己监听端口
Socket 连接 = 端口.accept();                  // ② 自己等客人上门
String 原始报文 = 读入(连接);                 // ③ 自己读原始 HTTP 文本
String 路径 = 手动解析(原始报文);             // ④ 自己拆 URL、拆请求头
String 参数 = 手动取参数(原始报文);           // ⑤ 自己解析表单数据
// ...还要自己管多线程、自己处理异常、自己区分静态和动态

有了 Tomcat,你只需写一个类、配一个映射,剩下的"接待流程"全部交给容器。这也是为什么真实项目里没有人从头写一个 Web 服务器——造轮子不划算,轮子早有人造好了。

💡 记忆口诀:Tomcat = Servlet 的房东。你只管"客人来了怎么招待",房租水电(端口、HTTP 解析、线程调度)房东全包。

⚠️ 常见错误

  1. 启动后访问 404:应用没放进 webapps 目录,或访问路径写错。为什么?Tomcat 默认部署目录就是 webapps,不在这个目录下的应用它根本不知道。怎么避免?把编译好的项目拷进 webapps,再用"应用名 + 路径"访问。
  2. 端口被占用:报 Port 8080 was already in use,说明别的程序占着 8080。为什么?每个端口同时只能有一个程序监听,先启动的占着不走。怎么避免?改端口(conf/server.xml)或结束占用进程(Windows 用 netstat -ano 查 PID)。
  3. 分不清静态和动态:静态页面放 webapps/应用名/ 下直接可访问;动态页面必须靠 Servlet 程序生成。为什么容易错?因为二者访问时都走浏览器,看起来差不多。怎么区分?动态页面通常带参数(?xxx=yyy)或路径里有 /servlet.do 之类后缀。
  4. 改完代码不重启 Tomcat:Java 改了类要重新编译、重启或热部署才生效,直接刷新浏览器看到的是旧页面。为什么?JVM 加载类一次后不会自动重新读取。怎么避免?开发期用 IDE 的热部署插件,或养成"改完就重启"的习惯。

📌 双语术语表(本讲)

中文 English 记忆点
万维网 World Wide Web (Web) 跑在互联网上的"网页服务"
浏览器 Browser 最常用的客户端
客户端 Client 主动发请求的一方
服务器 Server 保存和处理资源的一方
请求 Request 顾客下的单
响应 Response 商家给的结果
统一资源定位符 URL 网页世界的快递单
协议 Protocol 双方对话的规则
主机名 Host 服务器的名字
端口 Port 服务器上的门牌号
查询参数 Query String 捎给服务器的附加信息
域名系统 DNS 查 IP 的电话簿
静态网页 Static Page 现成的海报
动态网页 Dynamic Page 现场做的海报
Web 容器 Web Container Servlet 的房东

⭐ 本讲考点清单

  1. Web 的运作本质是"请求-响应"一问一答:浏览器是客户端,服务器负责保存和处理资源。
  2. 客户端-服务器架构:客户端主动请求、服务器被动响应,服务器常年在线、宕机业务即停。
  3. URL 六大组成:协议、主机名、端口、路径、查询参数、锚点;端口省略默认 80/443。
  4. 查询参数以 ? 开头、& 连接多个键值对;# 后的锚点不会发给服务器。
  5. HTTP 请求和响应都是纯文本报文,请求由"方法 + URL + 头部(+ 可选请求体)"构成。
  6. DNS 把域名解析成 IP 地址,相当于全球电话簿,且沿途多级缓存。
  7. 一次完整请求六步:输入网址 → DNS → TCP 连接 → 发请求 → 服务器处理 → 浏览器渲染。
  8. 静态网页内容写死、响应快;动态网页运行时生成、千人千面。
  9. Web 容器(Tomcat)负责监听端口、解析 HTTP、管理 Servlet 生命周期、处理并发。
  10. 请求-响应默认"无状态":一问一答、答完就散,想要记忆要靠 Cookie / Session。
  11. 常见排错链:DNS 挂了 → 无法解析;端口不通 → 连接失败;404 → 资源不存在。