从 Node.js 到 Spring MVC
熟悉 Express 或 Koa,再看 Spring 的路由注解并不难;真正陌生的是框架替代码完成了多少准备:Controller 谁来创建,Repository 为什么只有接口,方法参数怎么得到值,返回一个字符串为什么能生成整页 HTML。这组文章围绕这些问题阅读 Spring Petclinic。
源码选择官方 Spring Petclinic,固定在 500158f732419217507c7656904b8e6aa1bcc0d6;本地 origin 使用个人 fork。这份提交声明 Java 17,以 Spring Boot 4.1.0 为父项目,使用 Spring MVC、Thymeleaf、Bean Validation 和 Spring Data JPA。它是一个以服务端页面为主的样例,不把控制器假定成统一返回 JSON 的 REST API。
读者可以默认熟悉 HTTP、表单、JSON、Express / Koa 与数据库。Java 注解、Bean、代理和模型绑定会在必要位置解释,数据库操作主要作为已知的业务步骤。主线使用 Owner,让同一份表单和控制器贯穿入口、参数、对象装配与测试。
由于篇幅问题,全文分成 6 部分来讲。
第一篇《应用入口与页面请求》从 main 方法读到 Servlet 容器、DispatcherServlet 和控制器,先建立页面应用的处理链,再解释视图名、响应体与重定向的不同返回语义。
第二篇《控制器参数从哪里来》逐个拆解 page、Owner、BindingResult、Model 和 RedirectAttributes,追踪 ModelAttribute 如何准备对象,并区分类型转换和业务范围判断。
第三篇《表单绑定、校验与视图》沿着表单字段说明 Binder、@Valid 与模板的配合,解释为什么无效表单可以返回 200,以及实体映射、输入限制和公开 HTML 分别由什么决定。
第四篇《Bean 容器与构造器注入》回答 Controller 与 Repository 的对象来源:组件扫描、构造器注入、Spring Data 代理和 @Bean 配置分别做什么,并把应用单例与请求数据分开。
第五篇《沿着新增 Owner 读完整请求》串起打开表单、提交校验、保存、重定向和详情读取。成功与失败两条页面分支分别配图,说明 Model、flash 和 PRG 的职责。
第六篇《用 MockMvc 验证框架行为》阅读现成的无效表单测试,区分 Web 切片、Repository mock、JPA 与集成测试,并给出选择性运行命令和实际核对边界。
与FastAPI 系列和Go Web / Memos 系列对照时,可以沿相同的六个观察点阅读:入口、参数、输入输出边界、对象与请求上下文、完整流程、测试。Petclinic 没有这两份项目中的登录用户链路,因此对应位置用 Bean 容器解释对象来源,保留各项目真实的侧重点。