什么是 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(模型)

  • 功能描述:存储数据(如 ModelModelMapMap 接口),供视图渲染使用。

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)等绑定到方法参数。

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,View 会读取 JSP 文件,结合 Model 数据渲染为最终 HTML 内容。

7. 返回响应

  • 最终处理
    • 渲染后的结果(HTML 或数据)通过 DispatcherServlet 写回客户端(浏览器或接口调用方)。
    • 释放请求处理过程中使用的资源(如数据库连接、线程资源)。
五. 优势与适用场景
  • 优势
    • 松耦合架构: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 的自动配置,可进一步减少样板代码,提升开发效率。