场景

维护传统 Java Web 管理后台时,请求偶发串号、刷新后重复提交,问题往往不在语法,而在 Servlet 生命周期、转发与重定向、Cookie 与 Session 的边界没有理清。

原理

容器只创建少量 Servlet 实例,却会用多个线程并发调用 service。request 保存单次请求数据,session 跨请求关联用户,application 面向整个应用;JSP 最终也会编译成 Servlet。转发复用同一次请求,重定向则让浏览器发起新请求。

设计步骤

先画出浏览器、容器、Servlet 与会话存储的时序;再限定 Servlet 字段只放不可变依赖,把业务状态放到局部变量或外部存储;按查询与写入选择 GET、POST;最后为登录、跳转、刷新和并发请求补集成测试。

权衡

Session 编程简单,却带来服务端状态、集群复制和过期治理;Cookie 易于横向扩展,但容量小且可能被窃取。转发少一次网络往返,却不会改变地址栏;重定向边界清晰,但要防止开放重定向。

实践建议

不要在 Servlet 成员变量中缓存用户数据;写操作采用 PRG 模式避免刷新重放;Cookie 开启 HttpOnly、Secure、SameSite;集群会话优先集中存储并设置明确 TTL。传统技术仍常见于网关、老系统和框架底层,理解边界比背诵对象列表更重要。

落地检查

上线前还应做一次桌面演练:准备正常、边界、超时、重复与恶意输入,确认系统的返回、日志和指标彼此对应;在预发布环境模拟依赖不可用、进程重启和配置回滚,验证降级路径不会放大故障。上线时采用小流量观察,提前定义停止条件与负责人。稳定后复盘真实数据,删除没有收益的复杂度,并把新发现的约束补进测试、监控和设计记录,使方案能够随业务持续演进,而不是停留在一次性评审结论。