JavaEE 环境与程序设计 · 交互课程
技术演进接力链(M1 → M9)
  1. 1WEB 基础
    HTTP / Browser / WebServer
    静态页面写死,人人看到一样
  2. 2Servlet
    手写 if-else 分发不可扩展,无生命周期/并发管理
  3. 3JSP:参数散字符串
    参数散成一堆 String,取值靠字段名硬记
  4. 3JSP:scriptlet 塞逻辑
    scriptlet 把逻辑塞进页面,代码与 HTML 糊在一起
  5. 3JavaBean:数据对象化
    对象全靠 new、层层硬依赖
  6. 4Spring IoC
    Web 路由仍手写 web.xml/if-else、手动取参绑定,展示/业务/数据访问没分开
  7. 5MVC · SpringMVC
    数据在库里,访问是重复样板 + 拼串有注入风险
  8. 6MySQL
    Java 连库要手写五步,连接与资源管理全手动
  9. 7JDBC
    SQL 与 Java 混写、结果集逐行手映射、没有动态 SQL
  10. 8MyBatis
    四份配置 + web.xml 装配繁琐,部署要外部 Tomcat
  11. 9SpringBoot
    链尾 · 不考核

MVC 模式 · SpringMVC

承接上一章的死结
上一章(Spring IoC)的死结:Web 路由仍手写 web.xml/if-else、手动取参绑定,展示/业务/数据访问没分开。本章引入 MVC + SpringMVC 把三者拆开。

MVC 模式 · SpringMVC

目标:掌握 SpringMVC 请求处理流程与 Controller 开发,能完成 CRUD 小项目。

本模块在 IoC/DI 之上引入 MVC 框架:DispatcherServlet 统一调度、Controller 处理请求、ViewResolver 渲染视图。以真实工程 GuestBookSpringMVC 为样板,拆解「表单提交 → Controller → Model → JSP 回显」的完整闭环。

一、MVC 设计模式

MVC(Model-View-Controller)把「一次请求的处理」拆成三种职责,各管一段:

SpringMVC 是 MVC 在 Web 层的落地:Controller 由 @Controller 标注,DispatcherServlet 负责统一调度。

落到工程里,MVC 进一步对应三层架构——表示层(Controller/View)、业务逻辑层(Service)、数据访问层(DAO)。下面交互组件逐层看每层「只干自己的事」:

职责

接收请求、渲染视图、展示数据——只负责「跟用户打交道」

SpringMVC / SSM 里对应谁

@Controller + @RequestMapping + JSP(EL ${...})

典型写法
@RequestMapping("/hello.do")
public ModelAndView hello() {
    return new ModelAndView("hello", "message", msg);
}

请求自上而下穿过三层(Controller → Service → DAO),数据自下而上回到 View——每层只干自己的事,互不越界。

二、请求处理五步流程

客户端请求 → DispatcherServlet → HandlerMapping 找 Controller → Controller 返回 ModelAndView → ViewResolver 渲染视图。下面交互实验逐步看这条链路(对照 GuestBookSpringMVC):

交互实验:DispatcherServlet 分发五步时序(SpringMVCFlowDiagram)

先选一个 URL,再点「下一步」,看请求如何从浏览器一路走到 JSP 渲染。对照真实工程 GuestBookSpringMVC。

客户端请求
→
DispatcherServlet
→
HandlerMapping
→
Controller 执行
→
ViewResolver 渲染

客户端请求 —— 负责组件 浏览器

用户访问某个 .do 地址,HTTP 请求到达服务器

Model:数据——Controller 往里放业务对象/属性
View:视图——JSP 用 EL ${...} 从 Model 取值渲染
Controller:控制——@RequestMapping 方法处理请求、决定返回哪个 View

web.xml 把所有 *.do 交给 DispatcherServlet;spring-mvc.xml 里 <context:component-scan> 自动发现 @Controller,RequestMappingHandlerMapping 负责 URL→方法映射。

三、@RequestMapping 与 HandlerMapping

@Controller 类里的每个 @RequestMapping("...") 方法都是一个 handler。请求进来,HandlerMapping 按 URL 找到命中的方法:

交互实验:URL → @RequestMapping 命中(HandlerMappingDemo)

输入一个 URL(或点下面的预设),看 RequestMappingHandlerMapping 命中哪个 Controller 方法。支持 {占位符} 路径变量匹配。

命中 HelloWorldController.helloWorld(HttpSession)
@RequestMapping方法Controller
/hello.dohelloWorld(HttpSession)HelloWorldController
/login.dologin(request, User user, Model model, session)HelloWorldController
/logout.dologout(HttpSession)HelloWorldController
/user/{id}.dogetUser(@PathVariable Long id)UserController(教学示例) — {id} 为路径变量,如 /user/42.do → id=42

精确路径优先;含 {...} 的映射按「任意非 / 片段」匹配,如 /user/42.do 命中 /user/{id}.do(id=42)。无匹配通常返回 404。

支持精确路径(/hello.do)与路径变量占位符(/user/{id}.do → @PathVariable)。

四、数据传递:Model / ModelAndView / JSP EL

Controller 把数据放进 Model,ViewResolver 渲染的 JSP 用 EL 取出来:

交互实验:Model → JSP EL 数据流(ModelDataFlow)

选一个请求,点「下一步」,看 Controller 放进 Model 的数据如何被 JSP 用 EL 取出来渲染。

① Controller(放)

model.addAttribute("user", user);
return new ModelAndView("words", "message", message);

② Model / ModelMap(持有)

  • user : User(对象)
  • message : String

③ JSP(EL 取)

  • <h3>${message}</h3>
  • 当前用户:${user.username}
Controller 放入 Model —— model.addAttribute / new ModelAndView(...) 把业务对象/属性放进 Model

Model 是「本次请求」的数据容器:Controller 放、JSP 取,请求结束即失效;而 HttpSession 跨多次请求存活。要让用户「下次进来还记得」,得把对象同时放进 session(如本工程 login 里 session.setAttribute)。

new ModelAndView("hello", "message", msg) = 逻辑视图名 hello + 属性 message;JSP 里 ${message} 取值。要跨请求记住用户,还得 session.setAttribute。

五、spring-mvc.xml 与 web.xml

思考题

  1. DispatcherServlet、HandlerMapping、ViewResolver 各自负责什么?为什么需要「前端控制器」统一入口?
  2. @RequestMapping 写在类上和方法上有什么区别?
  3. Model 与 HttpSession 的作用域有何不同?何时该用哪个?
  4. new ModelAndView("hello", "message", msg) 三个参数各是什么含义?
  5. ViewResolver 的 prefix/suffix 如何把逻辑视图名拼成实际 JSP 路径?

学习小测验

学习小测验

Q1

DispatcherServlet 的作用是( )

Q2

SpringMVC 请求处理五步的正确顺序是( )

Q3

@RequestMapping 的作用是( )

Q4

HandlerMapping 的职责是( )

Q5

ViewResolver(视图解析器)的作用是( )

Q6

Model / ModelMap 的作用是( )

Q7

JSP 里 ${message} 的取值来源是( )

Q8

new ModelAndView("hello", "message", msg) 的含义是( )

Q9

在 MVC 三层架构里,「业务规则、事务边界」应放在哪一层?

Q10

数据访问层(DAO)的职责是( )

本章留下的死结
数据在数据库里,访问是重复样板 + 拼串有注入风险(下一章 MySQL)。