当前位置: 首页 > news >正文

Java面试(2025)—— Spring MVC

什么是Spring MVC

Spring MVC 是 Spring 框架的一个 基于 Java 的 Web 开发模块,它实现了 MVC(Model-View-Controller)架构模式,用于构建灵活、松耦合的 Web 应用程序。
它是 Spring 生态的核心组件之一,通过简化 HTTP 请求处理、数据绑定和视图渲染,帮助开发者高效构建企业级 Web 应用。

Spring MVC的优点

Spring MVC 是 Spring 生态中用于构建 Web 应用的核心模块,它的核心优势在于 模块化设计注解驱动开发,能够高效处理 HTTP 请求并支持灵活的视图技术。我个人认为它的主要优点可以从以下几个方面展开:

(1) 松耦合的模块化设计

首先,Spring MVC 基于 前端控制器模式DispatcherServlet),将请求分发、业务处理、视图渲染等职责分离。
这种设计让各组件(如 ControllerViewResolver)可以独立替换或扩展,比如从 JSP 切换到 Thymeleaf 只需修改配置,无需改动业务代码。

(2) 注解驱动的开发效率

其次,它通过 注解(如 @Controller@GetMapping)极大简化了开发。对比传统的 Servlet 或 Struts2,代码量减少 50% 以上,且意图更清晰。

(3) 强大的数据绑定与验证

Spring MVC 支持 自动参数绑定(如 @RequestParam@ModelAttribute)和 JSR-303 验证(如 @Valid)。开发者无需手动解析 HTTP 参数,还能通过 BindingResult 统一处理校验错误,提升代码健壮性。

(4) 灵活的视图技术整合

它支持多种视图技术(JSP、Thymeleaf、Freemarker),并能无缝切换。对于前后端分离项目,还可以直接返回 JSON/XML(通过 @ResponseBody),适应现代开发需求。

(5) 与 Spring 生态深度集成

作为 Spring 的一部分,它可以轻松整合其他组件,比如用 @Transactional 管理事务,或通过 Spring Security 实现权限控制。这种一致性降低了学习成本,也便于维护。

综上,Spring MVC 特别适合 需要快速开发要求高可维护性 的项目,比如企业级后台管理系统或 RESTful API。它的灵活性和与 Spring 生态的无缝整合,是许多团队选择它的主要原因。

Spring MVC的主要组件

Spring MVC 主要组件

Spring MVC 框架由多个核心组件组成,它们协同工作来处理 HTTP 请求并生成响应。以下是主要组件及其功能:

DispatcherServlet (前端控制器)

  • 核心控制器,负责接收所有请求
  • 将请求委托给其他组件处理
  • 继承自 HttpServlet

HandlerMapping (处理器映射器)

  • 确定哪个 Controller 应该处理当前请求
  • 默认实现:RequestMappingHandlerMapping
  • 将 URL 映射到对应的处理方法

HandlerAdapter (处理器适配器)

  • 实际调用处理器方法
  • 处理不同类型的处理器
  • 默认实现:RequestMappingHandlerAdapter

Controller (控制器)

  • 处理业务逻辑
  • 返回 ModelAndView 或直接响应
  • 通常使用 @Controller 注解标记

ViewResolver (视图解析器)

  • 解析逻辑视图名到实际视图
  • 常见实现:InternalResourceViewResolver
  • 支持多种视图技术(JSP, Thymeleaf等)

View (视图)

  • 负责渲染模型数据
  • 生成最终响应内容(HTML, JSON等)

HandlerExceptionResolver (异常处理器)

  • 处理控制器执行过程中抛出的异常
  • 可以自定义异常处理逻辑

MultipartResolver (文件上传解析器)

  • 处理 multipart 文件上传请求
  • 常见实现:CommonsMultipartResolver

什么是DispatcherServlet?

DispatcherServlet 是 Spring MVC 框架的核心组件,它充当了前端控制器的角色,负责协调整个请求处理流程。

主要职责

  1. 请求接收:作为 Servlet,它接收所有的 HTTP 请求
  2. 请求分发:将请求委托给适当的控制器进行处理
  3. 视图渲染:协调视图解析和渲染过程
  4. 异常处理:处理请求处理过程中出现的异常
  5. 结果返回:将最终响应返回给客户端

工作原理

  1. 接收客户端请求
  2. 查询 HandlerMapping 确定处理请求的 Controller
  3. 通过 HandlerAdapter 调用实际的 Controller 方法
  4. 处理 Controller 返回的 ModelAndView 或直接响应
  5. 通过 ViewResolver 解析视图名称
  6. 渲染视图并返回响应

什么是Spring MVC框架的控制器?

简明定义(先给结论)

Spring MVC控制器是处理客户端请求并返回响应的核心组件,它负责接收用户请求、协调业务逻辑处理,并决定如何响应客户端。

核心特性(展示深度)

可以补充以下关键点:

  • 注解驱动:主要通过@Controller@RestController注解标识
  • 请求映射:使用@RequestMapping及其变体(@GetMapping等)定义URL映射
  • 多返回值支持:可以返回视图名称、ModelAndView、响应体或ResponseEntity
  • 松散耦合:与视图技术解耦,支持JSP、Thymeleaf等多种视图
  • REST支持:通过@RestController简化RESTful API开发

工作流程(结合架构)

在Spring MVC架构中,控制器位于DispatcherServlet之后:

  1. DispatcherServlet接收到请求后
  2. 通过HandlerMapping找到匹配的控制器方法
  3. 方法执行后返回处理结果
  4. 结果经过视图解析器或消息转换器处理
  5. 最终生成响应返回客户端

Spring MVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?

Spring MVC中的控制器默认是单例的(Singleton),这是由Spring容器的默认作用域决定的。在Spring中,所有Bean默认都是单例的,包括使用@Controller@RestController注解的类。

单例模式带来的潜在问题

  1. 线程安全问题
  • 多个HTTP请求会并发访问同一个控制器实例
  • 如果控制器有实例变量(成员变量),这些变量会被所有请求共享
  • 可能导致数据混乱或并发修改异常
  1. 状态保持问题
  • 单例控制器不适合保存请求特定的状态
  • 例如:在成员变量中存储请求相关的数据会导致不同请求间的数据污染。

解决方案

1. 避免使用实例变量(推荐)

最佳实践是控制器中不定义任何实例变量,所有请求特定的数据都应通过方法参数传递。

2. 使用方法局部变量

所有请求特定的数据都应在方法内部创建:

请描述Spring MVC的工作流程?描述一下 DispatcherServlet 的工作流程?

时序图


注意:

  1. HandlerMapping返回的是Hander或者是处理器链(处理器+拦截器);
  2. 拦截器执行的三个时机:

(1)适配器调用前执行 (preHandle)

  • 时机:在 HandlerAdapter 调用控制器方法之前
  • 作用:权限校验、日志记录、参数预处理等
  • 中断能力:若任一拦截器的 preHandle 返回 false,后续拦截器和控制器方法均不会执行
  • 顺序:按拦截器配置的正序执行

(2)适配器调用后执行 (postHandle)

  • 时机:在 HandlerAdapter 调用控制器方法之后,但在视图渲染之前
  • 作用:修改模型数据、记录执行结果等
  • 注意:此时控制器已执行完毕,但响应未写入客户端
  • 顺序:按拦截器配置的逆序执行;

(3)请求完成后执行 (afterCompletion)

  • 时机:在视图渲染完成后(整个请求处理完毕时)
  • 作用:资源清理、性能监控统计等
  • 特点:无论请求成功或异常都会执行
  • 顺序:按拦截器配置的逆序执行

过滤器和拦截器

特性

过滤器(Filter)

拦截器(Interceptor)

所属规范

Servlet 规范

Spring MVC 机制

执行位置

DispatcherServlet

DispatcherServlet

依赖

依赖 Servlet 容器

依赖 Spring 容器

可访问对象

ServletRequest/Response

可以获取 HandlerMethod 等Spring对象

使用场景

底层请求/响应处理

业务相关的横切关注点

Spring MVC常用的注解有哪些?

Spring MVC 提供了丰富的注解来简化 Web 开发,以下是常用注解分类整理

请求映射相关

注解

作用

示例

@RequestMapping

通用请求映射(可指定HTTP方法、头等)

@RequestMapping(value="/users", method=RequestMethod.GET)

@GetMapping

简化GET请求映射

@GetMapping("/users/{id}")

@PostMapping

简化POST请求映射

@PostMapping("/users")

@PutMapping

简化PUT请求映射

@PutMapping("/users/{id}")

@DeleteMapping

简化DELETE请求映射

@DeleteMapping("/users/{id}")

@PatchMapping

简化PATCH请求映射

@PatchMapping("/users/{id}")

参数处理

注解

作用

示例

@RequestParam

获取URL查询参数或表单数据

getUser(@RequestParam("name") String username)

@PathVariable

获取URI模板变量

getUser(@PathVariable Long id)

@RequestBody

接收JSON/XML请求体

createUser(@RequestBody User user)

@RequestHeader

获取请求头值

getHeader(@RequestHeader("User-Agent") String agent)

@CookieValue

获取Cookie值

readCookie(@CookieValue("JSESSIONID") String sessionId)

@ModelAttribute

绑定参数到模型对象

addUser(@ModelAttribute User user) 或 在方法上标注

响应处理

注解

作用

示例

@ResponseBody

将返回值直接写入HTTP响应体

@ResponseBody User getUser() 或 类上标注@RestController

@ResponseStatus

自定义HTTP响应状态码

@ResponseStatus(HttpStatus.CREATED)

@RestController

@Controller + @ResponseBody组合

@RestController public class UserController { ... }

异常处理

注解

作用

示例

@ExceptionHandler

处理控制器内的异常

@ExceptionHandler(UserNotFoundException.class)

@ControllerAdvice

全局异常处理(配合@ExceptionHandler

@ControllerAdvice public class GlobalExceptionHandler { ... }

数据验证

注解

作用

示例

@Valid

触发JSR-303验证

createUser(@Valid @RequestBody User user)

@Validated

Spring的验证注解(支持分组验证)

updateUser(@Validated(Group.Update.class) User user)

@NotNull

字段非空校验(需配合@Valid

@NotNull private String username;

视图与模型

注解

作用

示例

@Controller

定义控制器类

@Controller public class UserController { ... }

@SessionAttributes

模型属性存入Session

@SessionAttributes("user")

@CrossOrigin

解决跨域问题

@CrossOrigin(origins = "https://example.com")

其他实用注解

注解

作用

示例

@InitBinder

自定义数据绑定逻辑

@InitBinder public void initBinder(WebDataBinder binder) { ... }

@DateTimeFormat

日期格式转换

@DateTimeFormat(pattern="yyyy-MM-dd") Date birthDate;

完整代码示例

关键说明:

  1. 组合注解:如@RestController@Controller+@ResponseBody的组合
  2. 参数绑定@RequestParam默认必传,可通过required=false改为可选
  3. 验证联动@Valid需与JSR-303注解(如@NotNull)配合使用
  4. RESTful设计:推荐使用@GetMapping/@PostMapping等简化注解

掌握这些注解可以覆盖90%的Spring MVC开发场景!

@Controller注解的作用

@Controller 是 Spring MVC 中最核心的注解之一,用于标记一个类作为控制器(Controller),专门处理 HTTP 请求并返回响应。以下是它的详细作用解析:

  1. 标识控制器类
    告诉 Spring 容器:当前类是一个 MVC 控制器,需要被扫描并管理其生命周期。
  2. 接收 HTTP 请求
    @RequestMapping 等注解配合,定义处理特定 URL 请求的方法。
  3. 协调模型(Model)和视图(View)
    在传统 MVC 模式中,控制器负责处理业务逻辑,返回视图名称(如 JSP/Thymeleaf),由视图解析器渲染。

@RequestMapping注解的作用

@RequestMapping 是 Spring MVC 中最核心的注解之一,用于将 HTTP 请求映射到特定的控制器方法或类上。它提供了灵活的 URL 匹配规则,支持定义请求方法、参数、头部等条件。以下是详细解析:

  1. URL 路径映射
    将 HTTP 请求的 URL 路径与控制器方法绑定,支持:
  • 精确路径(如 /users
  • 路径变量(如 /users/{id}
  • 通配符(如 /resources/**
  1. HTTP 方法约束
    指定处理的请求类型(GET/POST/PUT/DELETE 等)。
  2. 请求参数/头部过滤
    通过附加条件(如参数必须存在、头部匹配)进一步筛选请求。

@ResponseBody注解的作用

@ResponseBody 是 Spring MVC 中用于将方法返回值直接写入 HTTP 响应体的核心注解,通常用于构建 RESTful API 或处理 AJAX 请求。以下是它的详细解析:

  1. 跳过视图渲染
    不再通过视图解析器(如 JSP/Thymeleaf)渲染,而是直接将返回值序列化为 JSON/XML 等格式写入响应体。
  2. 自动内容协商
    根据请求的
    Accept 头或 URL 后缀(如 .json),自动选择合适的 HttpMessageConverter 进行序列化。
  3. 支持多种返回类型
    可返回 Java 对象、集合、字符串等,Spring 会自动处理序列化。

@PathVariable和@RequestParam的区别

@PathVariable@RequestParam 是 Spring MVC 中用于处理 HTTP 请求参数的两种核心注解,它们的主要区别体现在 参数来源使用场景URL 风格 上。以下是详细对比:

核心区别总结

特性

@PathVariable

@RequestParam

参数来源

URL 路径 中提取

URL 查询字符串 表单数据 中提取

URL 示例

/users/123

/users?id=123

是否必传

默认必传(除非指定默认值)

可通过 required=false

设为可选

RESTful 风格

是(推荐用于资源标识)

否(传统查询方式)

数据类型转换

自动(Spring 类型转换机制)

自动(Spring 类型转换机制)

使用场景对比

1. @PathVariable(路径变量)

  • 适用场景:标识 RESTful 资源唯一性(如 ID、用户名等)
  • 示例代码
  • URL 风格

2. @RequestParam(请求参数)

  • 适用场景:过滤、排序、分页等非核心参数
  • 示例代码
  • URL 风格

相关文章:

  • CentOS7系统安装Docker教程
  • 目标跟踪中的聚类算法:DBSCAN Kmeans GMM
  • 【第十六届 蓝桥杯 省 C/Python A/Java C 登山】题解
  • <数据集>小船识别数据集<目标检测>
  • 平板电脑做欧盟网络安全法案(EU)2022/30
  • 14.第二阶段x64游戏实战-分析人物的名字
  • 基于opencv和PaddleOCR识别身份证信息
  • Spring Boot 整合 JavaFX 核心知识点详解
  • 科学视角下的养生新范式——高压氧舱:重塑健康边界的氧护革命
  • 使用 Electron 打包可执行文件和资源:完整实战教程
  • Prompt 攻击与防范:大语言模型安全的新挑战
  • 文字、语音、图片、视频四个模态两两之间(共16种转换方向)的生成技术及理论基础的详细说明及表格总结
  • 【2025面试Java常问八股之redis】zset数据结构的实现,跳表和B+树的对比
  • 基于大模型的血栓性外痔全流程风险预测与治疗管理研究报告
  • Linux系统下docker 安装 redis
  • hadoop与spark的区别和联系
  • 蚂蚁全媒体总编刘鑫炜再添新职,出任共工新闻社新媒体研究院院长
  • n8n 中文系列教程_05.如何在本机部署/安装 n8n(详细图文教程)
  • Java 服务器端 jar 包内 class 文件替换与配置文件修改高级技术指南
  • 在 Spring Boot 项目中怎么识别和优化慢 SQL ?
  • 2025年度“沪惠保”今日开售:保费维持129元/人,进一步扩增国内外特药种类
  • 市场监管部门完成全国保健食品生产企业体系检查首轮全覆盖
  • 第1现场|俄乌互指对方违反复活节临时停火提议
  • 分离19年后:陈杨梅首度露面,父亲亲手喂棉花糖给女儿吃
  • 阿塞拜疆总统阿利耶夫将访华
  • “万人大院”重组,上海交大校长丁奎岭:人才培养事关生存发展,再难也要改