
1. Spring MVC 是什么?
Spring MVC 是 Spring 框架的 Web 层子框架,基于 MVC(Model-View-Controller)设计模式,用于开发 Java Web 应用(处理 HTTP 请求、响应),是 Spring 生态中替代 Struts2 的主流 Web 框架。
它与 Spring 无缝集成(共享 IOC 容器,Bean 可直接注入),核心目标是 简化 Web 开发:提供 URL 映射、参数绑定、视图渲染、拦截器、异常处理等 Web 开发必备功能,让开发者专注于业务逻辑而非底层请求处理。
核心特性:
• 与 Spring 无缝集成(无需额外整合配置)。
• 灵活的 URL 映射(注解式/XML 式配置)。
• 自动参数绑定(请求参数 → Java 对象,无需手动转换)。
• 支持多种视图技术(JSP、Thymeleaf、Freemarker 等)。
• 内置拦截器、异常处理、文件上传、跨域等功能。
2. Spring MVC 核心及原理
(1)MVC 设计模式在 Spring MVC 中的映射
• Model(模型):业务数据和逻辑(如 JavaBean、Service、Dao),负责数据处理。
• View(视图):用户界面(如 JSP、Thymeleaf),负责展示数据。
• Controller(控制器):@Controller 标注的类,接收 HTTP 请求,调用 Model 处理,将结果传递给 View 渲染。
(2)核心组件(核心骨架)
Spring MVC 的核心是 DispatcherServlet(前端控制器),所有请求都由它接收并协调其他组件完成处理,核心组件如下:
|
组件名称 |
作用 |
|
DispatcherServlet |
前端控制器(核心):接收所有 HTTP 请求,分发到对应组件。 |
|
HandlerMapping |
处理器映射器:根据请求 URL 查找对应的 Handler(Controller 方法),返回 HandlerExecutionChain(Handler + 拦截器)。 |
|
HandlerAdapter |
处理器适配器:适配不同类型的 Handler,执行 Handler 并返回 ModelAndView。 |
|
Handler(Controller) |
处理器:@Controller 标注的类,执行业务逻辑,返回 ModelAndView(数据 + 视图名)。 |
|
ViewResolver |
视图解析器:将视图名解析为具体视图对象(如 JSP 路径)。 |
|
ModelAndView |
封装业务数据(Model)和视图名(View)。 |
|
Interceptor |
拦截器:拦截请求/响应,实现日志、权限控制等功能。 |
(3)核心原理:请求处理流程(10 步详解)
1. 用户发送 HTTP 请求(如
http://localhost:8080/user/query?id=1001),请求被 Tomcat 接收后转发给 DispatcherServlet。
2. DispatcherServlet 调用 HandlerMapping,根据 URL 查找对应的 HandlerExecutionChain(包含 Controller 方法和拦截器)。
3. DispatcherServlet 调用 HandlerAdapter,适配 Handler(如解析请求参数、绑定到方法参数)。
4. HandlerAdapter 执行 Handler(Controller 方法),调用 Service/Dao 处理业务逻辑。
5. Handler 返回 ModelAndView(如 new ModelAndView(“user/detail”, “user”, userInfo))。
6. HandlerAdapter 将 ModelAndView 返回给 DispatcherServlet。
7. DispatcherServlet 调用 ViewResolver,根据视图名(如 user/detail)解析为具体视图(如
/WEB-INF/views/user/detail.jsp)。
8. ViewResolver 返回 View 对象给 DispatcherServlet。
9. DispatcherServlet 调用 View 的 render() 方法,将 Model 中的数据渲染到视图(如 JSP 填充数据)。
10. 渲染后的 HTML 响应通过 DispatcherServlet 返回给用户,流程结束。
3. Spring MVC 框架搭建
步骤 1:创建 Maven Web 项目
步骤 2:导入核心依赖
|
groupId |
artifactId |
version |
scope |
|
org.springframework |
spring-webmvc |
5.3.20 |
Spring MVC 核心依赖(自动依赖 Spring 核心) |
|
javax.servlet |
javax.servlet-api |
4.0.1 |
Servlet API 依赖(Tomcat 已提供,scope=provided) |
|
javax.servlet.jsp |
jsp-api |
2.2 |
JSP API 依赖 |
|
javax.servlet |
jstl |
1.2 |
JSTL 依赖(JSP 中使用 EL 表达式) |
步骤 3:配置 web.xml(注册 DispatcherServlet,配置前端控制器和字符编码过滤器)
步骤 4:编写 Spring MVC 配置文件(spring-mvc.xml)
步骤 5:编写 Controller 控制器
步骤 6:编写 JSP 视图
4. Spring MVC 常见面试题(基础 + 进阶 + 高级)
(1)基础面试题(概念与使用)
1. Spring MVC 的核心作用是什么?
• 接收 HTTP 请求并分发到对应 Controller 方法。
• 自动完成请求参数与 Java 对象的绑定(无需手动转换)。
• 调用 Service/Dao 处理业务逻辑。
• 将处理结果传递给视图渲染响应(如 JSP 填充数据)。
• 提供 Web 开发必备功能(拦截器、异常处理、文件上传、跨域等)。
2. @RequestMapping 注解的核心属性有哪些?
@RequestMapping 用于映射 HTTP 请求到 Controller 类或方法,核心属性:
• value/path:指定映射的 URL(如 value = “/user/query”)。
• method:指定请求方式(如 RequestMethod.GET/POST,简化为 @GetMapping/@PostMapping)。
• params:指定请求必须包含的参数(如 params = “id” 表明必须带 id 参数)。
• headers:指定请求必须包含的请求头(如 headers = “Accept=application/json”)。
• produces:指定响应体的媒体类型(如 produces = “application/json”,返回 JSON 数据)。
3. Spring MVC 如何接收请求参数?常见方式有哪些?
常见参数绑定方式:
• 基本类型参数:@RequestParam(“name”) String username(绑定 URL/表单参数)。
• 路径参数:@PathVariable(“id”) Integer userId(绑定 URL 路径参数,如 /user/{id})。
• JavaBean 绑定:直接接收 Java 对象(请求参数名与 Bean 属性名一致),如 public String addUser(User user)。
• JSON 参数:@RequestBody User user(接收 JSON 格式请求体,需开启 @EnableWebMvc 或注解驱动)。
• 日期类型:@DateTimeFormat(pattern = “yyyy-MM-dd”) Date birthday(指定日期格式转换)。
• 数组/集合:@RequestParam(“ids”) List<Integer> ids(绑定多个同名参数,如 ?ids=1&ids=2)。
4. Model、ModelMap、ModelAndView 的区别?
• Model:简化版接口,仅提供 addAttribute() 方法,用于存储视图数据(开发首选,轻量)。
• ModelMap:继承 LinkedHashMap,除 addAttribute() 外,支持 Map 所有方法(如 put()、get())。
• ModelAndView:封装“数据 + 视图名”,需手动指定视图名(如 new ModelAndView(“user/detail”, “user”, user)),适用于需要同时设置数据和视图的场景。
5. Spring MVC 的视图解析器作用是什么?常见实现有哪些?
• 作用:将 Controller 返回的“视图名”(如 user/detail)解析为具体的视图对象(如 JSP 路径、Thymeleaf 模板)。
• 常见实现:
○
InternalResourceViewResolver:默认,解析 JSP 视图(最常用)。
○ ThymeleafViewResolver:解析 Thymeleaf 视图(Spring Boot 推荐)。
○ FreeMarkerViewResolver:解析 Freemarker 视图。
○ BeanNameViewResolver:按 Bean 名称解析视图(自定义视图时使用)。
(2)进阶面试题(原理与流程)
1. Spring MVC 的请求处理流程详细步骤?
答案:核心 10 步(从请求到响应):
1. 用户发送 HTTP 请求,Tomcat 接收后转发给 DispatcherServlet。
2. DispatcherServlet 调用 HandlerMapping,根据 URL 查找 HandlerExecutionChain(Handler + 拦截器)。
3. DispatcherServlet 调用 HandlerAdapter,适配 Handler(解析请求参数、绑定到方法)。
4. HandlerAdapter 执行 Handler(Controller 方法),调用 Service/Dao 处理业务。
5. Handler 返回 ModelAndView(数据 + 视图名)给 HandlerAdapter。
6. HandlerAdapter 将 ModelAndView 返回给 DispatcherServlet。
7. DispatcherServlet 调用 ViewResolver,将视图名解析为具体 View。
8. DispatcherServlet 调用 View 的 render() 方法,渲染 Model 数据到视图。
9. 视图生成 HTML 响应,通过 DispatcherServlet 返回给用户。
10. 执行拦截器的 afterCompletion() 方法(请求处理完成后)。
2. Spring MVC 拦截器的实现方式和执行顺序?
• 实现方式:
a. 自定义拦截器类,实现 HandlerInterceptor 接口,重写 3 个方法:
▪ preHandle():请求处理前执行(返回 true 继续,false 终止)。
▪ postHandle():Controller 方法执行后、视图渲染前执行。
▪ afterCompletion():视图渲染后、响应返回前执行。
b. 在 Spring MVC 配置文件中注册拦截器:
• 执行顺序(假设有 2 个拦截器 A、B):
a. A.preHandle() → B.preHandle()(按注册顺序)。
b. 执行 Controller 方法。
c. B.postHandle() → A.postHandle()(按注册逆序)。
d. 视图渲染。
e. B.afterCompletion() → A.afterCompletion()(按注册逆序)。
3. Spring MVC 如何处理文件上传?
答案:Spring MVC 通过 MultipartResolver 实现文件上传,步骤如下:
1. 配置 MultipartResolver(Spring 5 内置 CommonsMultipartResolver):
2. 前端表单(需设置 enctype=”multipart/form-data”):
3. Controller 方法接收文件:
4. Spring MVC 如何解决跨域问题?
答案:跨域(CORS)是浏览器限制不同域名/端口/协议的请求访问,Spring MVC 解决方式:
1. 注解方式(推荐):在 Controller 或方法上添加 @CrossOrigin:
2. 全局配置(实现 WebMvcConfigurer):
3. 过滤器方式:自定义 CORS 过滤器,设置响应头 Access-Control-Allow-*。
5. Spring MVC 数据绑定的底层原理?
答案:数据绑定是 Spring MVC 自动将请求参数转换为 Controller 方法参数的过程,核心是 DataBinder:
1. 请求到达后,HandlerAdapter 触发数据绑定,创建 DataBinder 实例。
2. DataBinder 接收请求参数(
ServletRequestParameterMap)和目标参数类型(如 User 类)。
3. DataBinder 调用 ConversionService(类型转换器),将请求参数的字符串类型转换为目标类型(如 String → Integer、String → Date)。
4. 若转换失败,错误信息存入 BindingResult(可在 Controller 方法中获取并处理)。
5. 将转换后的参数注入到 Controller 方法,执行方法。
(3)高级面试题(深度应用与优化)
1. Spring MVC 的异常处理机制有哪些?底层原理是什么?
答案:Spring MVC 提供 3 种异常处理方式:
1. @ExceptionHandler(局部异常处理):在 Controller 中定义方法,处理当前 Controller 的异常:
2. @ControllerAdvice + @ExceptionHandler(全局异常处理):定义全局异常处理器,处理所有 Controller 的异常:
3. 实现 HandlerExceptionResolver(全局异常处理):自定义异常解析器,返回 ModelAndView。
• 底层原理:
当 Controller 方法抛出异常时,DispatcherServlet 调用
HandlerExceptionResolverComposite,遍历所有注册的 HandlerExceptionResolver,找到能处理该异常的解析器,生成 ModelAndView 并渲染异常页面。
2. Spring MVC 与 Struts2 的区别?
答案:核心区别(Spring MVC 更主流):
|
维度 |
Spring MVC |
Struts2 |
|
核心设计 |
基于方法(单例 Controller,方法线程安全) |
基于类(多例 Action,类成员变量存储请求参数) |
|
性能 |
更高(单例无反射实例化开销) |
较低(每次请求创建新 Action) |
|
配置方式 |
注解驱动(简洁) |
XML 配置为主(繁琐) |
|
参数绑定 |
方法参数绑定(清晰) |
类成员变量绑定(易混乱) |
|
拦截器机制 |
基于方法调用(细粒度) |
基于 Action 调用(粗粒度) |
|
集成性 |
与 Spring 无缝集成 |
需额外配置整合 Spring |
|
适用场景 |
企业级应用、微服务 |
传统 Web 应用(逐渐被淘汰) |
3. Spring MVC 如何实现异步请求处理?
答案:Spring MVC 3.2+ 支持异步请求(非阻塞 IO),适用于耗时操作(如调用第三方接口),核心方式:
1. 返回 DeferredResult<T>:
2. 返回 Callable<T>:
3. 基于 @Async 注解:
• 原理:异步请求释放 Tomcat 线程,耗时操作由后台线程执行,执行完成后再通过 Tomcat 线程响应客户端,提高服务器并发能力。
4. Spring MVC 的性能优化手段有哪些?
答案:常见优化手段:
1. 静态资源缓存:配置 Cache-Control 响应头,减少重复请求(如 CSS、JS、图片)。
2. 关闭不必要组件:如不使用 JSP 时,移除
InternalResourceViewResolver。
3. 优化参数绑定:避免复杂对象绑定,使用 @RequestParam 明确指定参数。
4. 启用异步请求:处理耗时操作,提高并发能力。
5. 优化拦截器:减少拦截器数量,避免在 preHandle() 中执行耗时操作。
6. 启用 GZIP 压缩:压缩响应数据(如 HTML、JSON),减少网络传输量。
7. 使用编译型模板:如 Thymeleaf 替代 JSP(渲染速度更快)。
8. 缓存频繁访问数据:如用 Redis 缓存热点数据,减少数据库查询。
9. 配置连接池:如 Druid 优化数据库连接管理,避免连接泄露。
5. Spring MVC 的 DispatcherServlet 是如何初始化的?
答案:DispatcherServlet 的初始化基于 Servlet 规范,核心步骤:
1. Tomcat 启动时,因 web.xml 中配置 load-on-startup=1,Tomcat 调用 DispatcherServlet 的 init() 方法。
2. init() 方法调用 initServletBean(),初始化 Spring MVC 的 Web 应用上下文(WebApplicationContext)。
3. WebApplicationContext 继承自 Spring 的 ApplicationContext,共享 Spring 核心容器的 Bean,同时扫描 Controller 等 Web 层 Bean。
4. 初始化核心组件:HandlerMapping、HandlerAdapter、ViewResolver 等(通过配置文件或自动发现)。
5. 初始化完成后,DispatcherServlet 处于就绪状态,接收 HTTP 请求。
