我接触web系统开发,是在2002年。我2000毕业那年刚到科研所时,机房里还飘着 Windows 98 的开机音乐,Web 开发正处在 “刀耕火种” 的年代。那时要做个能显示实时科研数据的页面,得靠 CGI 程序 —— 就像每次有人寄信,都要临时雇个分拣员(启动进程),处理完就解雇,效率低得惊人。

之前做的都是windows或linux相关的程序,02年开始流行做web系统。这时开始对web系统有了认知,但基本上是从 Servlet开始的。Servlet 本质是驻留在服务器里的 “常驻分拣员”(Java 类),Web 服务器收到请求后不用新建进程,只需唤醒一个线程让 Servlet 处理。它就像邮局里固定工位的职员,既能接收信件(HttpServletRequest),又能封装回信(HttpServletResponse),还懂各种 “邮政规程”(HTTP 协议)。更关键的是,它带着 Java 的 “天生优势”—— 一次编译到处运行,这在当时 Windows 与 Unix 混战的服务器市场,简直是跨平台的 “万能钥匙”。

为什么说它是 Java Web 的起源?因为在它之前,Java 技术只能在桌面应用里打转。Servlet 第一次让 Java 真正走进了 Web 世界,就像为 Java 开辟了通往互联网的 “第一座桥梁”。后来的 JSP、Struts、Spring MVC,全都是架在这座桥之上的建筑。

二、代码示例:从 “手写 HTML” 到 “框架封装”

原始 Servlet(2002 年的电商订单处理)
// 当年写的电商订单查询Servlet,记得调试了三天

public class OrderQueryServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

// 1. 手动解析请求参数(像在信封上找收件人地址)

String orderId = req.getParameter("orderId");

// 2. 调用业务逻辑(那会儿还没有Spring,直接new对象)

OrderService service = new OrderService();

Order order = service.getOrderById(orderId);

// 3. 手动拼接HTML(最折磨人的步骤)

resp.getWriter().write("<html><body>");

resp.getWriter().write("<h3>订单号:" + order.getId() + "</h3>");

resp.getWriter().write("<p>金额:" + order.getAmount() + "</p>");

resp.getWriter().write("</body></html>");

}

}

Spring MVC 的 “现代继承者”

// 现在的订单控制器,本质是Servlet的“精装修版”

@RestController

public class OrderController {

@Autowired

private OrderService service;

// DispatcherServlet帮我们做了参数解析、请求路由

@GetMapping("/order/{id}")

public OrderDTO getOrder(@PathVariable String id) {

Order order = service.getOrderById(id);

return OrderConverter.toDTO(order); // 无需手动写HTML

}

}

三、实战场景:OA 系统里的技术抉择

2005 年我们给某国企做 内网系统系统,面临过一次关键抉择:用 Servlet+JSP 还是 PHP?

  • Servlet 方案:我们用 Model2 模式(Servlet+JSP+JavaBean)实现公文流转。Servlet 做 “调度员”,接收用户的签批请求,调用 JavaBean 处理权限校验和流程更新,再转发到 JSP 显示公文页面。这种架构就像正规医院的分诊系统,各司其职,后来系统扩容到 500 人同时在线也没出问题。
  • PHP 备选方案:当时试做了个公告模块,PHP 确实写得快,直接在 HTML 里插代码。但到了公文归档这种复杂场景,业务逻辑和页面代码搅在一起,就像厨房和餐厅混在一间屋,维护时找个 bug 都要翻几百行代码。

最终选择 Servlet 的核心原因:国企 系统 需要稳定运行十年以上,Servlet 的编译型特性和强类型检查,能减少后期 “带病运行” 的风险。这也是为什么早期企业级应用几乎都倒向了 Java 阵营。

四、对比分析:四种 Web 技术的 “江湖纷争”

技术

核心特点

像什么场景

电商 / OA 中的适配性

痛点

CGI

进程级处理,语言无关

临时雇佣的快递员

小网站勉强可用,大促必崩

进程开销大,响应慢

ASP

脚本嵌入 HTML,Windows 专属

家庭厨房,做饭吃饭一锅端

OA 轻量模块可用

跨平台差,维护混乱

PHP

开源脚本,开发极速

快餐厅,出餐快但难办宴席

商品详情页等静态化场景

复杂业务逻辑难维护

Servlet

线程级处理,Java 生态

连锁酒店后厨,标准化运作

订单、支付等核心模块

早期需手写 HTML

印象最深的是 2003 年对比 CGI 和 Servlet 的性能:同样处理 1000 个订单查询,CGI 用了 47 秒,还占满了服务器内存;而 Servlet 只花了 8 秒,线程池就像待命的服务员,用完立刻归队待命。

五、常见陷阱:老程序员踩过的 “坑”

  1. 线程安全陷阱:2002 年做科研数据展示时,我在 Servlet 里定义了全局变量private int count = 0;,结果多用户访问时数据全乱了。后来才明白:Servlet 是单实例多线程,全局变量会被所有线程共享,就像多人共用一支笔,写出来的字肯定乱。
  1. 资源泄漏陷阱:早年写 OA 附件上传功能,忘记关闭InputStream,Tomcat 运行一周就报 “文件句柄耗尽”。现在想来,当时要是懂try-with-resources语法就好了,这也是 Servlet 开发从 “野蛮生长” 到 “规范成熟” 的缩影。
  1. 配置地狱陷阱:Servlet 2.5 时代,web.xml 里要写几十行映射配置,每次加新功能都要重启服务器。有次电商大促前改配置,手滑输错 URL,导致支付模块瘫痪了 10 分钟,至今想起来还冒冷汗。

六、最佳实践:穿越二十年的技术沉淀

  基础规范

  • 永远不要在 Servlet 中定义非 final 的全局变量,用ThreadLocal存储线程私有数据
  • 必须在finally块关闭流资源,Java 7 + 优先用try-with-resources

   框架选型

  • 中小项目直接用 Spring Boot 内嵌 Tomcat,省去 Servlet 容器配置
  • 大型微服务用 Spring Cloud Gateway,但要记得:底层的 DispatcherServlet 仍是 “总指挥”

云原生适配

  • 将 Servlet 应用打包成 Docker 镜像时,用 JDK 17 的 “瘦身模式”,镜像体积能从 GB 级降到 MB 级
  • 高并发场景启用 Servlet 3.0 的异步处理:req.startAsync(),就像餐厅接了大单后先开单子,后厨慢慢做,前台继续接单

性能优化

  • 用 Redis 缓存 Servlet 的计算结果,比如电商商品详情页,避免重复查询数据库
  • 对静态资源(JS/CSS)启用 Tomcat 的 Gzip 压缩,响应速度能提升 40%

七、现代价值:云原生时代的 “老当益壮”

今天当我按照自己的技术路线要写web这块,我打算从serlet开始写时,年轻同事问我:“都 2025 年了,还提 Servlet 干嘛?” 我笑着让他看 Spring Boot 的依赖包 ——spring-boot-starter-web里赫然躺着javax.servlet-api。

Servlet 在云原生时代的新价值,藏在三个地方:

  • 容器化适配:Tomcat 容器能秒级启动,正好契合云原生 “弹性伸缩” 的需求。我们的 OA 系统在早高峰(9 点签到)自动扩容到 8 个实例,低谷时缩为 2 个,每月省了 30% 服务器费用
  • 微服务基石:Spring Cloud 的服务通信、熔断降级,本质都是通过 Servlet 处理 HTTP 请求。就像高楼再花哨,地基还是钢筋混凝土
  • Serverless 兼容:阿里云 Function Compute 支持把 Servlet 打包成函数,按调用次数计费。有个客户的电商秒杀接口,用这种方式把峰值成本压到了传统部署的 1/5

最后小结:

整理旧硬盘时,翻出 2002 年写的 Servlet 代码,注释里还画着歪歪扭扭的流程图。从当年在 Windows 2000 Server 上调试 Tomcat,到现在用 K8s 部署 Spring Boot 应用,Servlet 就像一位沉默的老伙计,见证了 Java Web 从蹒跚学步到驰骋云端。

它或许不再是舞台中央的主角,但所有现代 Java Web 框架的根,都深深扎在 Servlet 这片土壤里。就像我们这些老程序员,或许不再写底层代码,但那些踩过的坑、总结的经验,早已成了技术传承的一部分。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐