Servlet:Java Web 的历史兼容层,并非现代 Web 核心模型!

📅 2026/6/25 22:31:38
Servlet:Java Web 的历史兼容层,并非现代 Web 核心模型!
Servlet并非为现代 Web 设计很多人首次接触 Java Web 多从 Servlet 开始自然而然认为它是 Java Web 的基础、所有框架的起点。然而若回顾历史并将其置于如今的系统中审视会发现一个反直觉的事实Servlet 并非为当下的 Web 设计更像是“旧时代 Web 服务器的扩展接口”如今用它做的事已远超其当初设想。Servlet 诞生时的 Web 状况Servlet 诞生的年代Web 本质上并非“应用平台”更像远程文档系统。页面是核心交互简单即“提交表单然后返回一个 HTML 页面”那时没有前后端分离、API 网关、微服务以及复杂的分布式系统。当时要解决的问题很朴素即如何在 Web Server 里嵌入一段 Java 代码使其能动态生成页面而非每次都 fork 一个 CGI 进程。Servlet 就在这样的背景下出现它本质上不是框架而是底层的运行在 Web 容器里的请求回调机制。Servlet 简单的模型Servlet 的核心是来一个请求调用一次方法然后把结果写回去即“void service(ServletRequest req, ServletResponse res)”。若去除所有框架包装其思路一直是线程进来处理请求线程出去生命周期结束。这背后默认了一整套假设如请求是短的、IO 是阻塞的、线程可以一一对应请求、系统不需要长期维持连接状态。在当时这些假设没问题但如今这些假设基本都变了。现代 Web 已非“请求 - 响应”模式如今的系统早已不是“点一下按钮返回一个页面”的时代。请求可能只是入口后面可能跟着 RPC、数据库、缓存、消息队列一条链路可能运行很久。同时WebSocket、SSE 这种长连接越来越常见HTTP 不再只是短生命周期的协议。更关键的是IO 成为核心成本而非线程本身。但 Servlet 模型仍默认一个请求绑定一个线程这导致现代系统的瓶颈在 IO而 Servlet 的抽象中心却是线程的错位。Servlet 异步未能解决问题从 Servlet 3.0 开始支持异步大致形式为“AsyncContext async request.startAsync(); async.start(() - { // do something async.complete(); });”。看似解决了线程阻塞问题但实际上在复杂业务中没人愿意这么写原因并非 API而是感觉不对。异步未改变 Servlet 的“世界观”Servlet 的异步本质上只是释放了线程但整个请求模型未变。请求仍绑定在容器里生命周期还是 request 驱动的上下文还是依赖 ThreadLocal 的。它只是换了处理“在哪个线程上跑”的方式未改变“这个东西本质上是请求驱动”的事实所以解决的是局部问题而非整体结构。上下文被线程绑死的麻烦在 Servlet 体系里很多东西默认绑定在当前线程上如请求上下文、安全上下文、事务、日志 trace大多靠 ThreadLocal 传递。一旦进入异步流程线程切换这些上下文就会中断要么手动传递要么做各种包装。最终会发现异步不是不能用而是使用成本太高让人犹豫是否使用。Servlet 难入业务核心Servlet 的异步更像是给容器自己用的能力而非为业务开发设计的模型。它能优化吞吐、处理一些 IO 场景但进入复杂业务编排如 RPC DB MQ 这种组合代码会迅速难以控制让人怀疑是系统不适合异步还是异步模型本身不适合业务。Spring 未改变 Servlet 本质很多人认为 Spring Boot 是现代 Web但实际上它只是把 Servlet 包起来了。DispatcherServlet 还是 ServletTomcat 还是那个模型。它做的是工程体验的优化而非执行模型的重构。本质上只是让 Servlet 变得“更好用”但未脱离它。ServletJava Web 的历史兼容层若不考虑历史包袱可以认为 Servlet 更像是 Java Web 的历史兼容层而非现代 Web 的核心模型。它能用是因为生态庞大而非它是最优解。未来框架需重新设计执行模型如今 Web 已改变AI Native 时代又在进一步改变开发方式。若未来框架走向“对话驱动”或“运行时生成”执行模型本身可能要重新设计。在那样的世界里若被 Servlet 这一层绑定很多事情将难以开展。正如所说Servlet 不是为现代 Web 设计的它只是现代 Java Web 不得不继续依赖的一段历史。