一、Spring MVC简介
为什么使用Spring MVC?
直接使用Servlet开发Web应用存在一些不便:
-
接收参数麻烦 :需要手动调用
request.getParameter(),并进行类型转换。 -
请求映射不灵活 :通常一个Servlet类(通过重写
service或doGet/doPost方法)主要处理一种类型的请求,管理大量Servlet比较繁琐。
什么是MVC设计模式?
MVC是一种经典的分层设计思想,将应用分为三层:
-
Model (模型):处理数据和业务逻辑。
-
数据模型:如POJO(实体类)。
-
业务模型:如Service、Mapper(DAO)。
-
-
View (视图):负责展示界面,与用户交互。如JSP、HTML。
-
Controller (控制器) :接收用户请求,调用模型处理,并决定返回哪个视图。如Servlet、Spring MVC中的
@Controller。
调用关系 :View-> Controller-> Model
与三层架构关系 :MVC是一种表现层的架构模式,而经典的三层架构(表现层、业务逻辑层、数据访问层)是更宏观的应用程序分层。MVC中的Controller和View通常属于三层架构中的"表现层"。
什么是Spring MVC?
Spring MVC是Spring Framework提供的一个基于MVC设计模式的Web框架模块。它本质上封装了Servlet,极大地简化了传统Web开发,让开发者能更专注于业务逻辑。
二、快速入门案例
1. 项目依赖 (pom.xml)
核心需要spring-webmvc,它通常包含了spring-context。开发时可以用tomcat7-maven-plugin插件运行。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.x.x</version>
</dependency>
2. 前端页面 (index.jsp)
<a href="/hello">打个招呼</a>
3. 控制器 (HelloController.java)
@Controller // 标识这是一个Spring MVC控制器
public class HelloController {
@RequestMapping("/hello") // 建立URL `/hello` 与该方法的映射
public ModelAndView hello() {
ModelAndView mv = new ModelAndView();
// 向请求域添加数据,相当于 request.setAttribute("msg", "...")
mv.addObject("msg", "师姐你好");
// 设置逻辑视图名,视图解析器会将其转换为物理路径
mv.setViewName("success");
return mv;
}
}
4. Spring MVC 核心配置文件 (springmvc.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="...">
<!-- 1. 组件扫描:注册带有@Controller等注解的Bean -->
<context:component-scan base-package="com.yourpackage.controller"/>
<!-- 2. 视图解析器:将返回的逻辑视图名解析为实际JSP路径 -->
<!-- 例如: "success" -> "/WEB-INF/pages/success.jsp" -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 3. 注解驱动:核心配置!启用@RequestMapping, @RequestBody等注解支持,
并自动注册必要的处理器映射器和适配器 -->
<mvc:annotation-driven/>
</beans>
5. 配置前端控制器 (web.xml)
<web-app>
<!-- 配置Spring MVC的核心控制器:DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定Spring MVC配置文件的路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 设置随容器启动而加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--
url-pattern 详解:
`/` :拦截所有请求(不包括.jsp),将动态请求交给Spring MVC处理,静态资源需特殊配置。
`/*`:拦截所有请求(包括.jsp),JSP页面也将被拦截,通常不这么配。
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
三、Spring MVC 核心组件与工作流程
-
DispatcherServlet (前端控制器) :请求的统一入口,负责协调各个组件。
-
HandlerMapping (处理器映射器) :根据请求的URL,找到对应的处理器(
Handler,即我们写的@Controller中的方法)。 -
HandlerAdapter (处理器适配器) :以统一的适配器模式去调用找到的处理器方法。
-
Handler (处理器):即我们的业务控制器方法,处理具体请求。
-
ViewResolver (视图解析器) :将处理器返回的逻辑视图名 (如
"success")解析为具体的物理视图路径 (如"/WEB-INF/pages/success.jsp")。 -
View (视图) :对视图(如JSP)进行渲染 ,将模型数据填充到
request域,并最终生成响应。
简化流程 :请求-> DispatcherServlet-> HandlerMapping-> HandlerAdapter-> Handler-> ViewResolver-> View-> 响应。
四、核心注解 @RequestMapping
作用 :在处理器方法 或控制器类 上声明,用于建立URL请求 与处理方法之间的映射关系。
使用场景:
-
在方法 上使用:为该方法映射一个URL。
-
在类 上使用:为类中所有方法的URL提供一个统一的父路径(窄化请求路径)。
主要属性:
-
value/path:指定请求的URL。 -
method:指定请求方法(GET, POST, PUT, DELETE等)。RequestMethod.POST
示例:
@Controller
@RequestMapping("/user") // 窄化路径,类中所有方法URL都以 `/user` 开头
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser() { ... }
// 简写形式(推荐)
@PostMapping("/delete") // 等价于 @RequestMapping(value="/delete", method=RequestMethod.POST)
public String deleteUser() { ... }
@GetMapping("/{id}") // 等价于 @RequestMapping(value="/{id}", method=RequestMethod.GET)
public String getUser(@PathVariable Long id) { ... }
}
五、处理器方法的返回值
-
ModelAndView:可同时返回模型数据和视图名。
public ModelAndView getInfo() { ModelAndView mv = new ModelAndView(); mv.addObject("data", someData); // 设置模型数据 mv.setViewName("pageName"); // 设置逻辑视图名 return mv; } -
String (最常用):返回逻辑视图名、重定向或转发路径。
-
返回视图名 :配合
Model参数传递数据。public String getInfo(Model model) { model.addAttribute("data", someData); return "pageName"; // 由视图解析器拼接 } -
重定向 :
redirect:前缀。两次请求,地址栏改变,request域数据不共享。public String save() { // 处理保存逻辑... return "redirect:/user/list"; // 重定向到列表页 } -
请求转发 :
forward:前缀。一次请求,地址栏不变,request域数据共享。public String forwardDemo() { return "forward:/some/internal/page"; }
-
六、请求参数的接收
Spring MVC 能自动将请求参数绑定到处理器方法的入参上。
-
接收少量基本类型参数 :参数名 与URL或表单中的字段名一致即可自动绑定。
// 请求:/find?name=Tom&age=20 @GetMapping("/find") public String find(String name, Integer age) { // 自动注入 System.out.println(name + ", " + age); return "success"; } -
接收POJO对象参数(多个参数) :表单字段名或URL参数名与POJO属性名一致,即可自动封装成对象。
public class User { private String username; private String password; // getter/setter... } // 表单:<input name="username">, <input name="password"> @PostMapping("/add") public String add(User user) { // 自动封装为User对象 System.out.println(user.getUsername()); return "success"; } -
接收RESTful风格参数 :使用
@PathVariable注解,将URL路径中的变量绑定到参数。// 请求:/user/delete/123 @DeleteMapping("/user/{id}") public String delete(@PathVariable("id") Long userId) { // 将 {id} 的值 123 绑定到 userId userService.delete(userId); return "redirect:/user/list"; }
希望这份梳理能帮助你快速理解和回顾Spring MVC的核心内容。在接下来的学习中,你会接触到更深入的内容,如数据校验、JSON处理、拦截器、文件上传等。如果有任何疑问,欢迎在评论区交流!