什么是 Spring MVC?
一. 什么是 Spring MVC?
Spring MVC 是 Spring 框架中用于构建 Web 应用程序 的模块,基于 MVC(Model-View-Controller)架构模式,旨在分离应用的输入、处理和输出逻辑,简化 Web 开发。
- 核心目标:通过解耦控制器(Controller)、模型(Model)和视图(View),使代码结构清晰,易于维护和扩展。
- 定位:轻量级、灵活的 Web 层解决方案,支持 RESTful 接口开发、表单处理、文件上传等功能,与 Spring 生态(如 Spring Boot、Spring Data)深度集成。
二. 核心特点
1. MVC 架构分离
- 控制器(
Controller
):处理用户请求,调用业务逻辑,返回模型数据和视图名称。 - 模型(
Model
):封装业务数据(如表单参数、数据库查询结果)。 - 视图(
View
):负责数据展示(如 HTML 页面、JSON/XML 数据)。 - 解耦优势:三者独立,便于开发、测试和维护。
2. 注解驱动开发
- 核心注解(代码格式突出):
@Controller
:标记控制器类。@RequestMapping
:映射 URL 路径到处理方法。@PathVariable
:获取 URL 中的动态参数(如/user/{id}
)。@RequestParam
:获取请求参数(查询参数、表单字段)。@ResponseBody
:直接返回数据(如 JSON),跳过视图渲染。
- 优势:简化 XML 配置,通过注解快速定义请求映射。
3. 灵活的请求处理
- RESTful 支持:通过
GET/POST/PUT/DELETE
等 HTTP 方法,映射同一 URL 到不同处理逻辑。 - 数据绑定:自动将请求参数转换为 Java 对象(如表单提交的
User
对象)。
4. 多种视图技术支持
- 内置引擎:支持 JSP、Thymeleaf、FreeMarker 等模板引擎。
- 前后端分离:通过
@ResponseBody
返回 JSON/XML 数据,适配接口开发。 - 自定义视图:实现
View
接口,支持 Excel、PDF 等任意输出格式。
5. 与 Spring 生态集成
- 深度整合:无缝对接 Spring 核心(依赖注入、事务管理)、Spring Boot(自动配置)、Spring Security(安全控制)等模块。
三. 核心组件与架构
Spring MVC 的核心组件围绕 DispatcherServlet(前端控制器) 设计,处理流程如下:
1. DispatcherServlet
- 功能描述:它是所有请求的入口,负责协调各组件完成请求处理。
- 配置方式:可在
web.xml
或 Spring Boot 中配置映射路径(如/*
)。
2. HandlerMapping(处理器映射器)
- 功能描述:根据请求 URL 查找对应的处理器(Handler,通常是 Controller 方法)。
- 映射方式:支持多种映射方式,包括基于注解(
@RequestMapping
)、简单 URL 匹配、自定义规则。
3. HandlerAdapter(处理器适配器)
- 功能描述:适配不同类型的处理器(如基于注解的控制器、旧版的
HttpRequestHandler
),调用处理器方法。
4. Controller(控制器)
- 功能描述:处理具体业务逻辑,返回
ModelAndView
(包含模型数据和视图名称)或直接返回数据(通过@ResponseBody
)。
5. Model(模型)
- 功能描述:存储数据(如
Model
、ModelMap
、Map
接口),供视图渲染使用。
6. ViewResolver(视图解析器)
- 功能描述:将控制器返回的视图名称(如
user/list
)解析为具体的View
对象(如 JSP 视图、JSON 视图)。
7. View(视图)
- 功能描述:渲染模型数据,生成最终响应(如 HTML 页面、JSON 数据)。
四. 工作流程
1. 请求到达 DispatcherServlet
- 流程描述:用户通过浏览器或客户端发送 HTTP 请求(如
GET /user/1
),请求被配置为前端控制器的DispatcherServlet
拦截,作为整个请求处理流程的起点。
2. 查找处理器(HandlerMapping)
- 核心交互:
DispatcherServlet
调用注册的HandlerMapping
(如RequestMappingHandlerMapping
)。HandlerMapping
根据请求 URL(如/user/1
)和 HTTP 方法(GET/POST 等),匹配到对应的 控制器方法(标记有@RequestMapping
等注解的方法)。
- 示例匹配:若控制器方法标注
@RequestMapping("/user/{id}")
,则路径/user/1
会被正确映射。
3. 调用处理器(HandlerAdapter)
- 适配作用:
DispatcherServlet
通过HandlerAdapter
调用目标处理器(控制器方法)。HandlerAdapter
负责处理不同类型的处理器(如基于注解的控制器、传统HttpRequestHandler
),统一调用入口。
- 参数绑定:
- 自动将 URL 路径参数(
@PathVariable
)、请求参数(@RequestParam
)、请求体(@RequestBody
)等绑定到方法参数。
- 自动将 URL 路径参数(
4. 处理业务逻辑
- 控制器职责:
- 调用服务层(Service)处理业务逻辑(如查询数据库、校验数据)。
- 将处理结果填充到
Model
中(用于视图渲染),或直接返回数据(如 JSON)。
- 返回形式:
ModelAndView
:包含视图名称(如user/detail
)和模型数据(如user
对象)。- 直接返回数据:通过
@ResponseBody
注解,返回 JSON/XML 等格式(如@RestController
场景)。
5. 解析视图(ViewResolver)
- 触发条件:当控制器返回
ModelAndView
或字符串视图名时,进入视图解析流程。 - 解析过程:
ViewResolver
(如InternalResourceViewResolver
)将逻辑视图名(如userDetail
)转换为物理视图(如/WEB-INF/jsp/userDetail.jsp
)。- 支持多种视图技术(JSP、Thymeleaf 等),或自定义视图实现。
6. 渲染视图
- 视图类型:
- 页面渲染:如 JSP/Thymeleaf 视图,使用
Model
数据生成 HTML 页面。 - 数据响应:如
MappingJackson2HttpMessageConverter
将对象转为 JSON,无需视图解析(由@ResponseBody
触发)。
- 页面渲染:如 JSP/Thymeleaf 视图,使用
- 示例流程:
若视图为 JSP,
View
会读取 JSP 文件,结合Model
数据渲染为最终 HTML 内容。
7. 返回响应
- 最终处理:
- 渲染后的结果(HTML 或数据)通过
DispatcherServlet
写回客户端(浏览器或接口调用方)。 - 释放请求处理过程中使用的资源(如数据库连接、线程资源)。
- 渲染后的结果(HTML 或数据)通过
五. 优势与适用场景
- 优势:
- 松耦合架构:MVC 各层分离,便于单元测试(如独立测试控制器逻辑)。
- 注解驱动简化开发:无需编写大量 XML,通过注解快速定义 URL 映射和数据绑定。
- 强大的扩展性:可自定义处理器映射器、适配器、视图解析器,适配复杂需求。
- 支持前后端分离:通过
@ResponseBody
返回 JSON 数据,轻松构建 RESTful API。
- 适用场景:
- 企业级 Web 应用:适合开发复杂的后台管理系统、门户网站(结合模板引擎渲染页面)。
- RESTful API 开发:作为微服务或前后端分离项目的接口层,返回 JSON/XML 数据。
- 多视图技术整合:需要同时支持页面渲染和 API 输出的项目(如既有后台管理页面,又有移动端接口)。
六. 与其他框架对比
- vs Struts 2:
- Spring MVC 更轻量,基于注解开发,性能更好;Struts 2 基于 XML 配置,配置复杂,存在历史安全问题(如 OGNL 注入)。
- vs Jakarta EE(Java EE)的 MVC 实现(如 JSF):
- Spring MVC 更灵活,贴近原生 Servlet 开发;JSF 基于组件模型,学习成本高,扩展性较弱。
- vs 轻量级框架(如 Spark、Vert.x):
- Spring MVC 功能全面,适合大型项目;轻量级框架更适合小型应用或特定场景(如异步非阻塞处理)。
七. 核心配置示例(XML 与 Java 配置)
XML 配置(传统方式)
代码语言:txt复制XML 配置(传统方式)
xml
<!-- web.xml 中配置 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- springmvc-servlet.xml 配置组件 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Java 配置(推荐,基于 @Configuration)
代码语言:txt复制Java 配置(推荐,基于 @Configuration)
java
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
// 自定义组件配置(如拦截器、消息转换器)
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");
}
}
// 自定义组件配置(如拦截器、消息转换器) @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**"); } }
总之,Spring MVC 以 “MVC 架构” 为核心,通过注解驱动和灵活的组件设计,简化了 Web 开发流程,尤其适合需要细粒度控制请求处理和视图渲染的场景。其与 Spring 生态的深度集成,使其成为企业级 Java Web 开发的首选方案之一。结合 Spring Boot 的自动配置,可进一步减少样板代码,提升开发效率。