07 · 综合复习与术语表(Review & Glossary)

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


7.1 全链路知识脉络

一封信从寄出到收到

一次 Web 请求,很像寄一封信。你(浏览器)先在信纸上写好内容(HTTP 请求),贴上邮票(请求头),投进邮筒(网络)。邮局(Web 容器 Tomcat)收到信后开始分拣:先看信封上的地址(URL),再决定派哪位分拣员(Servlet)处理。分拣员拆开信,读明白你的要求(解析参数、调用业务),然后写一封回信——回信可以是印好的宣传页(渲染后的 HTML 页面),也可以是一份数据清单(JSON)。到了现代,邮局的整个分拣调度体系(Spring 框架)统一接管了这些流程,我们只需要关心「信写什么、要什么结果」。

整条链路的示意图:

浏览器(发请求 / 收响应)
   │  HTTP 请求(方法、URL、头、体)
   ▼
Web 容器 Tomcat —— 开 8080 端口等请求
   ▼
DispatcherServlet(前端控制器)
   │  HandlerMapping 找处理方法
   ▼
Controller → Service 业务层 → Dao 数据层 → 数据库
   ▼
返回:视图(JSP / 模板渲染 HTML)或数据(JSON)

每个环节各司其职,可以对照着复习:

  • 浏览器:用户的操作入口,负责把用户动作封装成 HTTP 请求发出去,并渲染收到的响应。
  • HTTP 协议:请求和响应的「格式契约」——方法、URL、状态码、请求头、请求体,前后端都按这套格式通信。
  • Web 容器(Tomcat):监听端口、接收连接、把 HTTP 报文解析成请求对象,并最终把响应写回网络。
  • Servlet / Spring MVC:处理业务的核心程序,解析参数、调用业务逻辑、生成响应内容。
  • Session / Cookie:因为 HTTP 是无状态的,靠它们记住「你是谁、上次干过什么」。
  • JSP / 模板引擎:把 Java 数据填充进 HTML 模板,生成完整的页面;而 JSON 接口则是把数据原样返回给前端处理。
  • 数据库:数据的最终归宿。Dao 层负责把业务数据读写到数据库,是整个链路的「尽头」。

把这条链路和无状态联系起来:HTTP 本身记不住任何上下文,服务器处理完一次请求就「忘了你是谁」。所以 Session 在这里扮演「记忆」的角色——登录后把身份写进 Session,后续请求靠 JSESSIONID 找到它。可以说,无状态是 HTTP 的「出厂设置」,而 Session / Cookie 是后天的「补丁」。

💡 记忆口诀:一条线串到底——浏览器发 HTTP,容器接住给 Servlet,Session 记身份,模板 / JSON 出结果,Spring 全管起。


7.2 各章核心速记表

核心要点
Web 基础 浏览器-服务器模式(B/S);URL 组成(协议 / 主机 / 路径 / 查询串);请求-响应模型;静态 vs 动态资源
HTTP 请求行 / 请求头 / 请求体;GET vs POST;状态码 200 / 302 / 404 / 500;无状态特性
Servlet 生命周期 init-service-destroy;doGet / doPost;HttpServletRequest / HttpServletResponse;注解或 web.xml 映射
会话 Session Session 存服务端;Cookie 存浏览器;JSESSIONID 关联两者;登录状态维持
JSP / 模板 JSP = HTML + Java;脚本片段与表达式;EL 表达式取值;转发 vs 重定向
接口 / REST JSON 格式;接口 = URL + 方法 + 参数 + 返回;REST 资源化设计
Spring 框架 IoC / DI 容器管理对象;@Controller 处理请求;@Autowired 注入;Spring Boot 一键启动

这张表不是让你背,而是用来自查:每一章能不能不看笔记,说出它的核心问题、关键类、典型代码?能说出的越多,说明掌握越牢。速记的窍门是给每章一个「锚点」:Web 基础锚「URL」,HTTP 锚「状态码」,Servlet 锚「生命周期」,Session 锚「JSESSIONID」,JSP 锚「EL」,接口锚「JSON」,Spring 锚「容器」。复习时先报出锚点,再展开细节,效率高很多。

💡 记忆口诀:七章七锚点——URL、状态码、生命周期、JSESSIONID、EL、JSON、容器。背下七个词,就能撑起全课程框架。

复习节奏建议:先把七章锚点默写出来,再对着锚点展开写每一章的 2-4 条要点,能写多少写多少,写不出来的就是薄弱点,回到对应章节补。这样一轮下来,全课程的知识框架就扎实了。


7.3 易混概念对比表

Cookie vs Session

维度 Cookie Session
存储位置 浏览器端 服务器端
数据量 小(约 4KB) 相对大,可存对象
安全性 可被篡改,别放敏感信息 相对安全
生命周期 可设 Expires / Max-Age 默认随会话结束,可配超时
谁创建 服务器 Set-Cookie,浏览器保存 服务器创建,靠 JSESSIONID 关联
典型用途 记住偏好、免登录标记 存登录状态、购物车

选谁:凡是涉及身份和敏感信息,一律用 Session,Cookie 里最多存一个 JSESSIONID 或者非敏感偏好。因为 Cookie 存在浏览器本地,用户能改、能被窃取;Session 数据在服务器上,相对可控。

GET vs POST

维度 GET POST
用途 取数据 提交数据
参数位置 URL 查询串(?name=xx) 请求体
可见性 地址栏可见、留历史记录 地址栏不可见
幂等 是(重复执行结果相同) 否(重复提交可能有副作用)
缓存 可被缓存 一般不缓存
长度限制 受 URL 长度限制 相对宽松

选谁:查询用 GET,提交用 POST。登录、注册、下单、修改资料这类「会产生副作用」的操作,必须用 POST;只看不改的查询,用 GET 并方便缓存。

重定向(302)vs 请求转发(forward)

维度 重定向 redirect 请求转发 forward
实现 response.sendRedirect() 服务器内部转发
地址栏 变成新 URL 不变
请求次数 2 次(浏览器再发一次) 1 次(服务器内部完成)
跨应用 可以跨域名 只能本应用内
request 共享 不共享 共享
典型场景 登录后跳首页 表单校验后回显

一句话:重定向是「让浏览器重新去一次」,转发是「服务器内部帮你把活干完」。要跨应用跳转、要地址栏变化,用重定向;要保留 request 里的数据,用转发。

JSP vs Servlet vs Spring MVC

维度 JSP Servlet Spring MVC
定位 视图(页面) 处理请求 框架层
写代码 偏 HTML,内嵌 Java 偏 Java 注解式控制器
复杂度 高但省事
请求处理 需要配合 Servlet doGet / doPost @Controller 方法
典型场景 渲染页面 纯 Java 处理 现代 Web 开发

可以这样理解发展脉络:Servlet 负责「处理」但不擅长「展示」,于是有了 JSP 专门写页面;两者结合(JSP + Servlet)是经典的 MVC 手动实现。Spring MVC 在这个基础上把控制器、映射、参数绑定、视图解析全部框架化,写起来更简洁,还能和 IoC 容器无缝配合。

💡 记忆口诀:JSP 负责好看,Servlet 负责干活,Spring MVC 把两者和容器一起管起来。

@RequestParam vs @PathVariable

维度 @RequestParam @PathVariable
参数来源 ?page=2 查询串 /user/7 路径
对应 URL /list?page=2 /user/7
缺失时 报 400 或取默认值 路径不匹配直接 404
典型用途 分页、筛选、搜索关键词 资源 id、层级路径

一句话总结:路径里的变量用 @PathVariable,问号后面的参数用 @RequestParam——看到 URL 长什么样,就知道该用哪个。

💡 记忆口诀:Session 在服务器、Cookie 在浏览器;重定向地址栏变、转发不变;@PathVariable 是路标、@RequestParam 是问号。

⚠️ 常见错误

  1. 登录状态用 Cookie 存密码:明文存在浏览器本地,用户能直接看到、篡改,还有被窃取的风险。原因:Cookie 在客户端,可控性差。避免:密码这类敏感信息只存在服务器 Session 里,Cookie 只放 JSESSIONID。
  2. 提交表单用 GET:密码、个人信息全进 URL,留在浏览器历史记录和服务器日志里。原因:GET 参数放查询串。避免:一切会产生副作用、含敏感信息的请求用 POST。
  3. 跨应用却用 forward:想跳转到别的应用或域名,却用转发,结果不生效或报错。原因:forward 只能在当前应用内部完成。避免:跨应用必须用 redirect。
  4. Session 失效后没判空:Session 超时后 getAttribute 返回 null,代码不判空直接使用,抛 NullPointerException。原因:超时是常态,不能假设永远有效。避免:读取属性后先判空,为 null 就跳登录。
  5. 请求参数类型不匹配:前端传 ?age=abc,后端用 @RequestParam int age 接收,报 400。原因:框架无法把非数字转成 int。避免:类型不匹配时先做校验,或用字符串接收再转换。

7.4 综合小项目:注册 + 登录 + 返回 JSON

把全课程知识串进一个场景

把前面学的知识点串起来:参数接收(@RequestBody / @RequestParam)、Session 登录态(HttpSession)、JSON 返回(@RestController + 对象自动序列化)、状态码(ResponseEntity)。注册、登录、查当前用户这三件事,就是绝大多数 Web 应用的雏形。

@RestController
public class AuthController {
    Map<String, String> users = new HashMap<>();   // 模拟数据库

    @PostMapping("/register")   // 收 JSON,返回 200 / 409
    public ResponseEntity<String> register(@RequestBody Map<String, String> b) {
        if (users.containsKey(b.get("username")))               // 用户名已存在
            return ResponseEntity.status(409).body("用户名已存在");  // 冲突 409
        users.put(b.get("username"), b.get("password"));        // 存进「数据库」
        return ResponseEntity.ok("注册成功");                    // 200 OK
    }

    @PostMapping("/login")      // 校验密码,Session 记登录态
    public ResponseEntity<String> login(@RequestBody Map<String, String> b,
                                        HttpSession session) {
        String pwd = users.get(b.get("username"));
        if (pwd == null || !pwd.equals(b.get("password")))
            return ResponseEntity.status(401).body("用户名或密码错误"); // 401
        session.setAttribute("user", b.get("username"));        // 记住登录态
        return ResponseEntity.ok("欢迎," + b.get("username"));
    }

    @GetMapping("/me")          // 读 Session,判断是否登录
    public ResponseEntity<String> me(HttpSession session) {
        Object user = session.getAttribute("user");
        if (user == null)
            return ResponseEntity.status(401).body("未登录");
        return ResponseEntity.ok("当前登录:" + user);
    }
}

以注册为例走一遍:前端 POST /register,把 {"username":"alice","password":"123"} 放进请求体 → Spring 按 @RequestBody 自动反序列化成 Map → 方法判断用户名是否已存在,存在返回 409,不存在就存进 Map 并返回 200。整个过程,框架负责「收信、拆信、回信」的通用部分,你只写「判断、存储」这两行业务。

这段代码浓缩了全课程多个考点,逐一盘点:

  • 请求方式:注册和登录用 @PostMapping(提交),查询用 @GetMapping(获取)——对应 7.3 的 GET vs POST。
  • 参数接收:前端提交 JSON,用 @RequestBody 接收并自动转成 Map 或对象;查询串参数则用 @RequestParam
  • Session 登录态:登录成功后把用户名写进 HttpSession,之后每次请求都能通过 session.getAttribute("user") 判断「谁在登录、是否登录」——对应 JV-04 的会话管理。注意 Session 默认存在服务器内存里,重启应用就会丢失,真实项目常常用 Redis 做共享会话来存登录态。
  • 状态码:用 ResponseEntity.status(409)status(401) 精确表达「冲突」「未认证」,而不是一律返回 200——对应 JV-02 的状态码。前端的 axios、fetch 也是根据状态码决定走成功还是错误回调,所以规范返回状态码不是小事。
  • JSON 返回@RestController 让返回的字符串和对象自动变成 JSON 写进响应体——对应本讲的 Spring MVC。

⚠️ 常见错误

  1. 状态码只用 200:密码错了也返回 200,前端只能靠 body 里的文字判断成功失败,不规范也不便于程序处理。原因:把错误当成功返回。避免:客户端错误用 4xx 状态码表达,200 只给真正成功。
  2. 密码校验用 ==:两个字符串用 == 比较的是引用地址而不是内容,结果永远是 false。原因:== 对引用类型比较的是地址。避免:字符串比较一律用 .equals()
  3. 没有登出接口:Session 一旦建立就一直有效,用户无法主动退出,有安全风险。原因:只记得登录,忘了退出。避免:提供登出接口调用 session.invalidate() 销毁会话。
  4. 参数未判空直接使用:前端没传 username,b.get("username") 返回 null,后续 containsKey(null) 或拼接 null 出问题。原因:外部输入不可信。避免:入参先判空、做基础校验。

7.5 综合思考练习题

  1. 为什么登录态存 Session,而不是每个请求都把密码发过来? 答:密码每次都发,等于把最敏感的凭证暴露在网络里,一旦被抓包就泄露。Session 的做法是:登录成功后服务器只发一个随机的 JSESSIONID,浏览器每次请求只带这个 ID,服务器根据 ID 找到对应的 Session 数据。这样密码只在登录那一刻传输一次,之后都靠 ID 识别身份,安全得多。这也是为什么很多网站能「记住登录状态」——服务器可以配置 Session 的有效期,让长时间不操作也不用重新登录。
  2. 为什么提交表单用 POST? 答:GET 的参数拼接在 URL 里,会留在浏览器历史记录、被代理缓存、还受长度限制;而表单提交往往包含密码等敏感信息和大量数据,用 POST 把这些内容放进请求体,既不在地址栏暴露,也没有长度限制,还能避免刷新时重复提交的副作用。
  3. @Controller 和 @RestController 返回同一个字符串,效果有什么不同? 答:@Controller 会把字符串当作「视图名」,去查找同名的 JSP / 模板文件来渲染页面;而 @RestController 会把字符串当作「数据」,直接写进响应体返回给前端。所以前后端分离、要返回 JSON 的接口用 @RestController,渲染传统页面用 @Controller。实际开发里返回 JSON 的接口几乎清一色用 @RestController,只有需要服务端渲染页面的老项目才用 @Controller。
  4. 为什么说 Spring 实现了控制反转? 答:传统代码里,对象需要谁就自己 new 谁,创建和管理的控制权在程序员手里;Spring 里对象只声明「我需要什么」,由容器统一创建、管理、注入。控制权从「程序员主动 new」反转为「容器被动提供」,这就是「反转」。好处是解耦——换实现不用改调用方代码。
  5. Session 失效后访问受保护资源会发生什么? 答:Session 超时后,服务器上的数据被销毁,session.getAttribute("user") 返回 null。接口判断发现没登录,返回 401 状态码,提示「未登录」。用户需要重新走登录流程,服务器再发新的 Session。
  6. 一次完整 GET 请求经过哪些环节? 答:浏览器把用户操作封装成 HTTP 请求 → 经网络到达 Tomcat → 交给 DispatcherServlet → HandlerMapping 找到对应 Controller 方法 → 方法解析参数、调用 Service / Dao 处理 → 把结果交给 DispatcherServlet → 序列化成 JSON 写进响应 → 浏览器收到并渲染。每一步各司其职,整个链路就是 7.1 那张图。
  7. REST 风格下,查询和删除用户应该用什么方法和路径? 答:REST 用 HTTP 方法表达操作语义——查询用 GET /users/7,删除用 DELETE /users/7,新增用 POST /users,修改用 PUT /users/7。同样的路径,方法不同代表的操作就不同,这样接口语义清晰、一目了然。

7.6 整体复习建议

三轮复习法

第一轮:按 7.2 速记表把七章锚点默写出来,再对照每章展开要点,把「写不出来」的地方标红,回到对应章节补课。第二轮:集中看 7.3 的对比表和 7.4 的代码,把容易混淆的概念逐行看懂,重点理解「为什么」,而不只是「是什么」。第三轮:做 7.5 的思考题,先盖住答案自己答一遍,再对照答要点补充遗漏。三轮下来,知识点就从「看过」变成「会写」。

  • 横向对比:把 7.3 的五组对比(Cookie/Session、GET/POST、重定向/转发、JSP/Servlet/MVC、@RequestParam/@PathVariable)各用一句话背下来,这是最常考、也最容易混的部分。
  • 纵向串线:用 7.1 的链路图把每章「挂在」对应环节上,画一遍图等于复习一遍全课程。
  • 代码重现:7.4 的综合示例亲手敲一遍、改几个地方(比如加个登出接口),比单纯看十遍都管用。

最后再扫一遍术语表,能中译英、英译中各说出「是什么」,就说明全课程基本过关了。


📌 完整术语表(全课程 30+ 条)

中文 English 记忆点
浏览器 browser 发请求收响应的客户端
服务器 server 提供服务的机器
请求 / 响应 request / response 客户端发、服务端回
无状态 stateless HTTP 记不住你
方法 method GET / POST / PUT / DELETE
状态码 status code 200 / 302 / 404 / 500
重定向 redirect 302,浏览器重新请求
请求转发 forward 服务器内部跳转
会话 session 服务端记身份
会话 ID session ID JSESSIONID 关联
Cookie cookie 浏览器存小数据
Servlet servlet 处理请求的 Java 程序
生命周期 lifecycle init-service-destroy
模板引擎 template engine 页面模板渲染
表达式语言 EL JSP 取值语法
接口 API 程序间通信契约
JSON JSON 前后端通用数据格式
序列化 serialize 对象转 JSON
REST REST 资源化接口风格
控制反转 IoC 创建权交给容器
依赖注入 DI 容器送依赖上门
Bean bean 容器管理的对象
容器 container 管理 Bean 生命周期
控制器 controller 接收请求的方法
服务层 service 业务逻辑
数据访问层 DAO 数据库访问
自动配置 auto-configuration 免手工装配
内嵌服务器 embedded server 打进应用的 Tomcat
起步依赖 starter 一键拉齐依赖
前端控制器 front controller 所有请求先过它

⭐ 全课程考点清单

  1. Web 基础:B/S 模式、URL 组成、请求-响应模型
  2. HTTP 报文格式:请求行、请求头、请求体
  3. GET 与 POST 的区别与选择
  4. 常见状态码:200、302、404、500
  5. HTTP 无状态特性与解决方案
  6. Servlet 生命周期与 doGet / doPost
  7. Session 与 Cookie 的区别
  8. 登录状态维持:Session + JSESSIONID
  9. 重定向与转发的区别
  10. JSP 与 Servlet 的关系、EL 表达式
  11. JSON 语法与序列化
  12. 接口与 REST 风格设计
  13. 框架的意义:解决重复样板代码
  14. IoC 与 DI 核心思想
  15. Spring 常用注解:@Controller / @RestController / @Autowired
  16. Spring MVC 请求处理流程
  17. Spring Boot 三大特性
  18. 综合链路:浏览器 → HTTP → 容器 → Servlet / Session → Spring