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 风格

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天翼云手机断开连接2小时关机

2025-04-21 天翼云手机断开连接2小时自动 天翼云手机 4元1个月 天翼云手机永不关机 天翼云手机不休眠 天翼云手机断开连接时,界面显示:离线运行,2小时后自动关机 电脑每小时自动连接一次 手机每小时自动连接一次

Redis——数据结构

目录 1.动态字符串SDS 1.1SDS底层源码 1.2 SDS动态扩容 1.3动态字符串SDS优点 2.IntSet 2.1底层结构 2.2有序性 2.3.IntSet结构扩容 2.4总结 3.Dict 3.1底层结构 3.2.Dict扩容 3.3Dict收缩 3.4.Dict的rehash 1.分配空间 2. 设置 rehashidx 3. 渐进式 rehash…

C++ GPU并行计算开发实战:利用CUDA/OpenCL加速粒子系统与流体模拟

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…

LeetCode算法题(Go语言实现)_54

题目 给你两个正整数数组 spells 和 potions ,长度分别为 n 和 m ,其中 spells[i] 表示第 i 个咒语的能量强度,potions[j] 表示第 j 瓶药水的能量强度。 同时给你一个整数 success 。一个咒语和药水的能量强度 相乘 如果 大于等于 success &a…

内网穿透快解析免费开放硬件集成SDK

一、行业问题 随着物联网技术的发展,符合用户需求的智能硬件设备被广泛的应用到各个领域,而智能设备的远程运维管理也是企业用户遇到的问题 二、快解析内网穿透解决方案 快解析是一款内网穿透产品,可以实现内网资源在外网访问,…

Python+Word实现周报自动化的完整流程

一、技术方案概述 自动化报表解决方案基于以下技术组件: Python 作为核心编程语言python-docx 库用于处理 Word 文档pandas 库用于数据处理和分析matplotlib 或 plotly 库用于数据可视化Word 模版作为报表的基础格式 这种方案的优势在于:保留了 Word 文…

elastic/go-elasticsearch与olivere/elastic

在 Go 语言中,与 Elasticsearch 交互的客户端库有多种选择,其中 github.com/elastic/go-elasticsearch/v8 和 github.com/olivere/elastic/v7 是两个常用的库。这两个库的功能和用途有一些差异,以下是它们的详细对比: 1. github.c…

deepseek + kimi制作PPT

目录 一、kimi简介二、deepseek生成内容三、生成PPT四、编辑PPT 一、kimi简介 kimi是一款只能ppt生成器,擅长将文本内容生成PPT。 在这里,​​DeepSeek 负责内容生成与逻辑梳理​​,​​Kimi 优化表达与提供设计建议​​。 二、deepseek生…

【八大排序】冒泡、直接选择、直接插入、希尔、堆、归并、快速、计数排序

目录 一、排序的介绍二、排序算法的实现2.1 直接插入排序2.2 希尔排序2.3 直接选择排序2.4 堆排序2.5 冒泡排序2.6 快速排序2.7 归并排序2.8 比较排序算法的性能展示2.9 计数排序 个人主页<— 数据结构专栏<— 一、排序的介绍 我们的生活中有很多排序&#xff0c;比如像…

linux 查询目录文件大小

​ 在 Linux 系统中&#xff0c;准确地掌握目录和文件的大小对于磁盘空间管理至关重要。​本文将详细介绍如何使用 du&#xff08;disk usage&#xff09;命令逐层查看目录和文件的大小&#xff0c;并结合 sort 命令对结果进行排序&#xff0c;以便有效地识别和管理占用…

如何简单几步使用 FFmpeg 将任何音频转为 MP3?

在多媒体处理领域&#xff0c;FFmpeg 以其强大的功能和灵活性而闻名。无论是视频编辑、音频转换还是流媒体处理&#xff0c;它都是专业人士和技术爱好者的首选工具之一。在这篇文章中简鹿办公将重点介绍如何使用 FFmpeg 进行音频格式转换&#xff0c;提供一些常用的转换方式&am…

通信信号分类识别

通信信号分类识别 AlexNet网络识别InceptionV3、ResNet-18、ResNet-50网络识别 采用短时傅里叶变换将一维信号转换为二维信号&#xff0c;然后采用经典神经网络进行识别 支持识别BASK,BFSK,BPSK,QPSK,8PSK,QAM和MSK。 AlexNet网络识别 在这里插入图片描述 InceptionV3、Re…

TPshop项目-服务器环境部署(部署环境/服务,检查部署环境/服务,上传TPshop项目到服务器,配置文件的更改,安装TPshop)

目录 部署环境/服务&#xff0c;检查部署环境/服务 检查部署环境/服务 上传TPshop项目到服务器&#xff0c;配置文件的更改&#xff0c;安装TPshop 部署环境/服务&#xff0c;检查部署环境/服务 一般部署环境&#xff0c;会根据开发写的部署文档来一步一步的部署环境。 部署…

C++入门基础:命名空间,缺省参数,函数重载,输入输出

命名空间&#xff1a; C语言是基于C语言的&#xff0c;融入了面向对象编程思想&#xff0c;有了很多有用的库&#xff0c;所以接下来我们将学习C如何优化C语言的不足的。 在C/C语言实践中&#xff0c;在全局作用域中变量&#xff0c;函数&#xff0c;类会有很多&#xff0c;这…

缓存 --- Redis基本数据类型

缓存 --- Redis基本数据类型 Redis Intro5种基础数据类型 Redis Intro Redis&#xff08;Remote Dictionary Server&#xff09;是一款开源的高性能键值存储系统&#xff0c;常用于缓存、消息中间件和实时数据处理场景。以下是其核心特点、数据类型及典型使用场景&#xff1a; …

Redis命令——list

列表类型是用来存储多个有序的字符串&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;⼀个列表最多可以存储个元素 在 Redis 中&#xff0c;可以对列表两端插入&#xff08;push&#xff09;和弹出&#xff08;pop&#xff09;&#xff0c;…

Android Jetpack Compose 状态管理解析:remember vs mutableStateOf,有啥不一样?为啥要一起用?

&#x1f331;《Jetpack Compose 状态管理解析&#xff1a;remember vs mutableStateOf&#xff0c;有啥不一样&#xff1f;为啥要一起用&#xff1f;》 在 Jetpack Compose 的世界里&#xff0c;UI 是响应式的。这意味着当状态发生变化时&#xff0c;UI 会自动重组&#xff0…

使用 PCL 和 Qt 实现点云可视化与交互

下面我将介绍如何结合点云库(PCL)和Qt框架(特别是QML)来实现点云的可视化与交互功能&#xff0c;包括高亮选择等效果。 1. 基本架构设计 首先需要建立一个结合PCL和Qt的基本架构&#xff1a; // PCLQtViewer.h #pragma once#include <QObject> #include <pcl/point…

mybatis plus打印sql日志到指定目录

1、mybatis plus打印sql日志 参考文档&#xff1a;mybatis plus打印sql日志_mybatisplus日志打印-CSDN博客 2、修改 修改InfoLevelLogger Override public void debug(String s) {// 修改这里logger.info(s);log.debug(s); } 增加&#xff1a;log.debug(s); 修改logback.x…

vue3 watch和watchEffect 的用法和区别

在 Vue 3 里&#xff0c;watch 和 watchEffect 都是用于响应式数据变化的 API&#xff0c;但它们在使用方法和应用场景上存在差异。下面详细介绍它们的用法和区别。 用法 watch watch 用于监听特定的响应式数据源&#xff0c;当数据源发生变化时&#xff0c;会执行相应的回调…