Java Spring “MVC ”面试清单(含超通俗生活案例与深度理解)

一、Spring MVC 核心组件相关

  1. 请解释 DispatcherServlet 的作用,为什么它被称为"前置控制器"?

• 核心解答:DispatcherServlet 是 Spring MVC 整个请求流程的"总协调中枢",所有客户端发起的请求(比如查询数据、提交表单)都会先经过它,再由它统一调度 HandlerMapping、HandlerAdapter、ViewResolver 等其他组件,决定"哪个组件处理请求、按什么顺序执行",避免组件之间直接交互,极大降低了整体耦合度。它不负责具体业务逻辑,只专注流程统筹,因此被称为"前置控制器"。

• 思考理解:DispatcherServlet 是请求进入 Spring MVC 框架的唯一"入口大门",就像所有事务都要先找"总负责人",再由总负责人分配任务,而非各组件自行对接。比如日常工作中,所有外部合作需求都先找"项目负责人",再由负责人分给对应开发、测试团队,负责人不做具体执行,只把控整体节奏。

• 生活例子:类比"学校的教务处总协调室"------学生的所有事务(选课、查成绩、申请补考)都先到总协调室(DispatcherServlet)。协调室不会自己帮学生选课(做业务),而是看事务类型:选课就联系选课系统老师(Handler)、查成绩就对接成绩管理老师(ViewResolver)、申请补考就找教学管理老师(HandlerAdapter),全程由协调室安排,确保学生事务不混乱、不遗漏。

• 实际开发注意点:Spring Boot 项目中,DispatcherServlet 会自动装配,默认映射所有"/"开头的请求;若需排除静态资源(如 .js、.css、图片文件),可在配置类中通过 addResourceHandlers 方法设置资源映射路径,避免它处理无关请求,减少性能消耗。

  1. Handler 是什么?实际开发中对应什么角色?

• 核心解答:Handler 是 Spring MVC 中的"业务执行者",专门负责处理具体的业务逻辑(比如查询用户信息、生成订单、删除商品数据),相当于传统 Java Web 开发中的 Servlet 或 Struts 框架里的 Action。它只关注"如何完成业务需求",不关心请求从哪里来、结果怎么返回给客户端------这些流程性工作全由其他组件处理。

• 思考理解:Handler 是开发中最核心的"干活组件",也是开发者编写代码的主要对象。它遵循"单一职责"原则:比如"用户管理"业务对应"用户 Handler",里面包含新增用户、查询用户、修改用户的代码;"订单业务"对应"订单 Handler",专注订单相关操作,两者互不干扰,后期维护时能快速定位对应业务代码。

• 生活例子:类比"学校的专业课老师"------学生选了"Java 编程"这门课(请求),最终要由 Java 老师(Handler)来授课(执行业务逻辑)。老师不用管学生怎么选课(请求路径匹配)、学生的选课信息怎么录入系统(参数处理),只需要专注把"Java 编程"这门课教好,完成"授课"这个核心动作。

• 实际开发注意点:现代 Spring MVC 开发中,Handler 就是加了 @Controller 注解的 Java 类(比如 UserController、OrderController),类中的方法通过 @GetMapping/@PostMapping/@PostMapping 等注解绑定具体请求路径(比如 @GetMapping("/user/detail") 绑定"查询用户详情"的请求),这些方法就是具体的 Handler 实现。

  1. HandlerMapping 的核心作用是什么?如何理解它的"映射"功能?

• 核心解答:HandlerMapping 是 Spring MVC 的"请求导航器",负责根据请求的 URL 地址、请求方法(GET/POST/PUT/DELETE)、请求头信息等,找到能处理该请求的 Handler。比如客户端发起 /user/list 的 GET 请求,它会告诉 DispatcherServlet:"这个请求该由 UserController 里的 list 方法处理",但它不直接调用 Handler,只返回"请求与 Handler 的匹配结果"。

• 思考理解:HandlerMapping 解决了"请求该找谁处理"的关键问题。如果没有它,DispatcherServlet 就得逐个询问所有 Handler"你能处理这个请求吗",就像在学校里找老师不看课程表,逐个教室问,效率极低;有了 HandlerMapping,就像查课程表找老师,一秒定位目标,大幅提升请求处理效率。

• 生活例子:类比"学校的课程表"------学生想上"数据库原理"课(请求),查看课程表(HandlerMapping),发现"每周三下午2点,数据库原理课在3号楼201教室,由张老师授课"(匹配结果),就知道该找张老师(Handler),不用问其他老师。这里的"课程名称-老师"对应关系,就是 HandlerMapping 负责的"请求-Handler"映射。

• 实际开发注意点:Spring MVC 提供多种 HandlerMapping 实现,最常用的是 RequestMappingHandlerMapping,它专门处理加了 @RequestMapping 注解的 Handler 方法,支持按 URL、请求方法、请求头、请求参数等多维度匹配请求;Spring Boot 会自动装配该组件,无需开发者手动配置。

  1. HandlerInterceptor 是什么?常见的使用场景有哪些?

• 核心解答:HandlerInterceptor 是 Spring MVC 的"请求拦截器",本质是一个接口,开发者可以通过实现这个接口,在 Handler 执行前、执行后、响应返回给客户端前,插入自定义逻辑(比如登录验证、请求日志记录、权限检查、接口访问频率限制)。它不干扰 Handler 的核心业务逻辑,只做"辅助性检查或记录",且支持配置多个拦截器,按注册顺序执行。

• 思考理解:HandlerInterceptor 就像请求的"过滤网+记录仪"------不符合条件的请求(比如未登录用户访问个人中心)会被拦截在 Handler 之外,直接返回错误响应;符合条件的请求会被允许通过,同时还能记录请求的关键信息(比如请求发起者的 IP 地址、请求时间、请求路径),方便后期排查问题或做数据统计。它的核心价值是"通用逻辑抽离",避免在每个 Handler 里重复写登录验证、日志记录等代码。

• 生活例子:类比"学校教学楼门口的值日生"------学生要进教学楼上课(Handler 执行),值日生(HandlerInterceptor)会做三件事:① 进门前检查学生是否带校园卡(Handler 执行前:登录验证),没带卡就不让进;② 学生进楼后,值日生在登记表上记录"XX学生,XX时间进入教学楼"(Handler 执行后:日志记录);③ 学生放学出楼时,值日生确认学生没有带走出教学用品(响应返回前:资源检查)。值日生不参与教学(不做业务),只负责"进出管理",确保教学楼秩序。

• 实际开发注意点:使用 HandlerInterceptor 需两步操作:第一步,实现 HandlerInterceptor 接口,重写 preHandle(Handler 执行前)、postHandle(Handler 执行后)、afterCompletion(响应返回前)三个方法,在对应方法中编写拦截逻辑;第二步,创建配置类实现 WebMvcConfigurer 接口,重写 addInterceptors 方法,将自定义拦截器注册到 Spring 容器中,并指定拦截的请求路径(比如 /user/** 拦截所有用户相关请求)和无需拦截的路径(比如 /login 不拦截登录请求)。

  1. HandlerExecutionChain 包含什么内容?为什么需要"执行链"这个设计?

• 核心解答:HandlerExecutionChain 是 Spring MVC 的"处理器执行链",包含两部分核心内容:一是"目标 Handler"(即要执行的业务处理器,比如 UserController 的 detail 方法),二是"与该 Handler 绑定的 HandlerInterceptor 列表"(可能有一个或多个拦截器)。它的作用是将"业务处理"和"拦截处理"打包成一个完整的执行单元,确保 Handler 执行时,所有相关拦截器的逻辑能按顺序同步生效,避免拦截器和 Handler 脱节。

• 思考理解:HandlerExecutionChain 相当于"业务+辅助"的"组合套餐"------比如一份"早餐套餐"里有主食(包子,对应 Handler)和配菜(鸡蛋+豆浆,对应两个拦截器),两者必须一起提供,才能满足用户的早餐需求。如果没有执行链,拦截器和 Handler 是分散的,可能出现"Handler 执行了,但拦截器没生效"的情况(比如没做登录验证就执行了"查询用户信息"的 Handler),导致业务漏洞。

• 生活例子:类比"学校的'上课+检查'流程包"------学生上"Java 编程"课(执行链),里面包含"Java 老师授课"(Handler)和"值日生检查校园卡"(第一个拦截器)、"课代表收作业"(第二个拦截器)。上课前必须先过值日生检查,上课后课代表收作业,流程固定且连贯,不会出现"老师已经开始上课,值日生还没检查校园卡"的混乱情况。

• 实际开发注意点:HandlerExecutionChain 由 Spring 框架自动创建,开发者无需手动实例化。多个拦截器的执行顺序遵循"注册顺序决定执行顺序"的规则:preHandle 方法按拦截器注册顺序执行(先注册的先执行),postHandle 和 afterCompletion 方法按注册逆序执行(后注册的先执行)。比如先注册"登录拦截器",再注册"日志拦截器",则 preHandle 是"登录拦截→日志拦截",postHandle 是"日志拦截→登录拦截"。

  1. HandlerAdapter 的作用是什么?为什么需要"适配"功能?

• 核心解答:HandlerAdapter 是 Spring MVC 的"业务辅助器",在 Handler 执行前,帮它完成"前置准备工作"------比如将前端传的字符串参数转换成 Integer/Date 等 Java 类型、验证表单参数是否符合规则(比如手机号格式是否正确)、将分散的请求参数封装成 JavaBean 对象(如把"name=张三&age=25"封装成 User 对象)。它让 Handler 不用关心参数处理,只需专注业务逻辑,实现"业务与参数解耦"。

• 思考理解:HandlerAdapter 解决了"Handler 多样化"带来的适配问题。比如有的 Handler 需要 Integer 类型的用户 ID 参数,有的需要 String 类型的用户名参数,有的需要自定义的 User 对象参数;如果没有 Adapter,每个 Handler 都要自己写参数转换、封装的代码,重复且繁琐。Adapter 相当于"翻译官",统一处理所有参数问题,DispatcherServlet 只需和 Adapter 交互,不用管 Handler 要什么类型的参数。

• 生活例子:类比"老师的助教"------Java 老师(Handler)要上"Java 集合"这节课(执行业务),助教(HandlerAdapter)会提前做准备:① 把老师的课件从 PDF 转成 PPT(参数类型转换);② 检查学生的预习作业是否完成(参数验证);③ 把学生的作业按"姓名-作业内容"整理成表格(封装 JavaBean)。老师不用管课件格式、作业检查,只需专注讲课,大幅减少非业务工作量。

• 实际开发注意点:Spring MVC 中最常用的 HandlerAdapter 是 RequestMappingHandlerAdapter,专门适配加了 @RequestMapping 注解的 Handler 方法;Spring Boot 会自动装配该组件,无需手动配置。若需自定义参数转换(比如将前端传的"2024-10-10"字符串转成 LocalDate 类型),可实现 Converter 接口编写转换逻辑,再注册到 Spring 容器中,HandlerAdapter 会自动使用该转换器。

  1. ModelAndView 是什么?传统开发和前后端分离开发中用法有何不同?

• 核心解答:ModelAndView 是 Spring MVC 的"数据与视图打包容器",包含两部分内容:一是 Model(业务数据,比如查询到的用户列表、订单详情),二是 View(视图标识,比如"userList""orderDetail")。传统开发中,Handler 执行完业务后,会将数据存入 Model,指定视图标识,封装成 ModelAndView 返回给 DispatcherServlet,用于后续视图渲染;前后端分离开发中,前端负责视图渲染,后端只需返回数据,因此 ModelAndView 会为 null,改用 @ResponseBody 直接返回 JSON 数据。

• 思考理解:传统开发中,ModelAndView 是"后端连接数据与视图的桥梁"------比如查询用户列表后,Model 装着用户数据,View 告诉 DispatcherServlet"用哪个页面展示数据";前后端分离后,"数据"和"视图"分开,后端不用管页面,自然不需要 ModelAndView,只需把数据以 JSON 格式传给前端,让前端自己渲染页面。

• 生活例子:类比"老师的'课件与板书提纲'"------传统教学中(传统开发),老师(Handler)讲完课后,会把课件(Model 数据)和板书提纲(View 标识,比如"第三章知识点总结")整理好(封装成 ModelAndView),交给课代表(DispatcherServlet),课代表再根据板书提纲找对应的黑板(视图),把课件内容写在黑板上(渲染视图);线上教学中(前后端分离),学生(前端)自己有笔记本(视图),老师只需把课件(数据)发给学生,学生自己整理笔记,不用老师提供板书提纲(ModelAndView 为 null)。

• 实际开发注意点:前后端分离项目中,几乎不会用到 ModelAndView;若不小心在加了 @ResponseBody 的方法里返回 ModelAndView,Spring 会把它当成普通 Java 对象转成 JSON,导致前端拿到包含"model""view"字段的错误数据,需特别注意。

  1. ViewResolver 的作用是什么?如何将"逻辑视图"解析为"物理视图"?

• 核心解答:ViewResolver 是 Spring MVC 的"视图路径解析器",负责将 ModelAndView 中的"逻辑视图名"(比如"userList""orderDetail"),根据预设的解析规则(如前缀、后缀),转换成真实的"物理视图路径"(比如"/WEB-INF/jsp/userList.jsp""/templates/orderDetail.html"),让 DispatcherServlet 能找到具体的视图文件,完成数据渲染。

• 思考理解:ViewResolver 解决了"简化视图路径编写"的问题。传统开发中,视图文件通常放在固定目录(如 /WEB-INF/jsp/),如果每个 Handler 都写完整路径(比如每次都写"/WEB-INF/jsp/userList.jsp"),会有大量重复代码;有了 ViewResolver,开发者只需写逻辑视图名("userList"),它会自动补全前缀(/WEB-INF/jsp/)和后缀(.jsp),生成物理路径。

• 生活例子:类比"学校的教室分布图"------老师(Handler)说"这节课去'3号楼的数据库教室'上课"(逻辑视图名),学生(DispatcherServlet)看教室分布图(ViewResolver),发现"3号楼的数据库教室"对应的具体位置是"3号楼205教室"(物理视图路径),就知道该去哪个教室。分布图的"3号楼-楼层-教室号"对应规则,就是 ViewResolver 的"前缀-逻辑名-后缀"解析规则。

• 实际开发注意点:传统 JSP 开发中,常用的 ViewResolver 是 InternalResourceViewResolver,只需在配置文件中设置前缀(如 /WEB-INF/jsp/)和后缀(如 .jsp)即可;若使用 Thymeleaf 模板,对应的 ViewResolver 是 ThymeleafViewResolver,Spring Boot 引入 Thymeleaf 依赖后会自动装配;前后端分离项目中,因无需视图渲染,可忽略 ViewResolver 的配置。

二、Spring MVC 传统工作流程(非前后端分离)

  1. 请完整描述 Spring MVC 传统开发的工作流程,并用生活例子类比?

• 核心解答:传统开发流程以"后端返回完整页面"为目标,全程由 DispatcherServlet 主导,共7个步骤:

  1. 客户端发起请求(比如访问 /user/list 查看用户列表),请求先到达 DispatcherServlet;

  2. DispatcherServlet 调用 HandlerMapping,根据请求的 URL 和方法,找到能处理该请求的 Handler(比如 UserController 的 list 方法);

  3. DispatcherServlet 调用 HandlerAdapter,通知它准备执行对应的 Handler;

  4. HandlerAdapter 完成参数处理(类型转换、封装、验证),调用 Handler 执行业务逻辑,Handler 执行完后返回 ModelAndView(含用户列表数据和"userList"逻辑视图名),HandlerAdapter 将 ModelAndView 转回给 DispatcherServlet;

  5. DispatcherServlet 调用 ViewResolver,将"userList"逻辑视图名解析为物理视图路径(如 /WEB-INF/jsp/userList.jsp);

  6. DispatcherServlet 将 ModelAndView 中的用户列表数据,填充到物理视图(userList.jsp)中,完成页面渲染;

  7. DispatcherServlet 将渲染好的完整页面响应给客户端,客户端浏览器展示页面。

• 思考理解:传统流程的核心是"后端既管数据又管页面",每个组件按"接收请求→匹配 Handler→处理参数→执行业务→解析视图→渲染页面→返回响应"的顺序协作,开发者只需专注编写 Handler(业务逻辑)、View(页面模板)和 Model(数据封装),流程性工作全由 Spring MVC 自动完成。

• 生活例子:类比"学生在学校查询期末成绩的完整流程":

  1. 学生(客户端)到教务处(DispatcherServlet)申请查询期末成绩(发起请求);

  2. 教务处老师(DispatcherServlet)查看课程表(HandlerMapping),发现"成绩查询"由成绩管理老师(Handler)负责;

  3. 教务处老师叫成绩管理老师的助教(HandlerAdapter),说"帮老师准备一下成绩查询的资料";

  4. 助教(HandlerAdapter)整理学生的选课信息(参数处理),交给成绩管理老师(Handler),老师查询成绩后,将"学生成绩表(Model 数据)"和"成绩公示表模板名(逻辑视图名)"整理好(ModelAndView),交给助教,助教再转回给教务处老师;

  5. 教务处老师查看教室分布图(ViewResolver),找到"成绩公示表模板"对应的具体位置(物理视图路径:3号楼公告栏);

  6. 教务处老师将学生成绩表贴到公告栏(填充数据到视图),完成"成绩公示页面"的渲染;

  7. 教务处老师通知学生去公告栏查看成绩(响应页面),学生看到完整的成绩公示(客户端展示页面)。

• 实际开发注意点:传统流程依赖 JSP、Freemarker、Thymeleaf 等后端模板技术,现在企业开发中已很少使用,但理解该流程能帮开发者掌握 Spring MVC"组件协作"的核心逻辑,为学习前后端分离流程打下基础。

三、Spring MVC Restful 接口流程(前后端分离)

  1. Restful 接口流程和传统流程的核心区别是什么?@ResponseBody 有什么作用?

• 核心解答:两者的核心区别在"返回结果处理"和"视图环节":传统流程返回 ModelAndView(数据+视图),需 ViewResolver 解析视图并渲染页面;Restful 流程用 @ResponseBody 标记 Handler 方法,直接返回 JSON 格式数据,ModelAndView 为 null,无需视图解析和页面渲染。具体流程如下:

  1. 客户端发起 Restful 请求(比如 /api/user/1 查询 ID 为1的用户),请求到达 DispatcherServlet;

  2. DispatcherServlet 调用 HandlerMapping,根据请求 URL 和方法,找到对应 Handler(比如 UserController 的 getById 方法);

  3. DispatcherServlet 调用 HandlerAdapter,通知它执行该 Handler;

  4. Handler 被封装成 ServletInvocableHandlerMethod(Spring 对 Handler 方法的封装),HandlerAdapter 调用该方法执行业务逻辑(查询 ID 为1的用户);

  5. Handler 执行完成后,HandlerAdapter 调用 HandlerMethodReturnValueHandler(核心实现是 RequestResponseBodyMethodProcessor)处理返回值:

◦ 创建 ServletServerHttpResponse(Spring 对原生 HTTP 响应对象的封装);

◦ 通过 HttpMessageConverter(如 Jackson 转换器),将 Handler 返回的 User 对象写入 ServletServerHttpResponse 的输出流;

◦ 自动将 User 对象序列化为 JSON 字符串(如 {"id":1,"name":"张三","age":25});

  1. 因 @ResponseBody 标记,无需处理视图(ModelAndView 为 null),DispatcherServlet 直接将包含 JSON 数据的响应返回给客户端,前端接收 JSON 并渲染页面。

• 思考理解:Restful 流程的核心是"后端只负责数据,前端负责视图",彻底分离前后端职责:后端专注"提供正确的数据",不用关心前端怎么展示;前端专注"用数据渲染页面",不用关心数据怎么查询。@ResponseBody 相当于"告诉 Spring:这个方法的返回值是给前端的数据,不用找视图",是前后端分离的关键注解。

• 生活例子:类比"学生线上查询作业成绩的流程":

  1. 学生(前端)在手机学习 APP 上,发起"查询数学作业成绩"的请求(/api/homework/math),请求先到学校的线上教学系统(DispatcherServlet);

  2. 线上系统(DispatcherServlet)查看"功能对应表"(HandlerMapping),发现"作业成绩查询"由数学老师(Handler)负责;

  3. 线上系统通知数学老师的助教(HandlerAdapter):"让数学老师查一下这个学生的作业成绩";

  4. 助教(HandlerAdapter)将学生的作业 ID 传给数学老师(Handler),老师查完成绩后,告诉助教"学生作业成绩是90分,作业评语是'步骤清晰'"(返回 User 对象);

  5. 助教(HandlerMethodReturnValueHandler)将成绩整理成"姓名:张三,作业:数学,成绩:90,评语:步骤清晰"的文字格式(JSON 序列化),存入系统的消息模板(ServletServerHttpResponse);

  6. 线上系统不用找公告栏(无需视图),直接将"成绩文字"发给学生的 APP(响应 JSON),学生在 APP 上看到成绩(前端渲染页面)。

• 实际开发注意点:@RestController 注解是 @Controller + @ResponseBody 的组合,用在类上时,类中所有方法都会自动返回 JSON,无需每个方法单独加 @ResponseBody,是前后端分离项目的常用注解;若需自定义 JSON 格式(如日期统一为"yyyy-MM-dd"),可配置 Jackson 的 ObjectMapper,设置日期格式化规则。

  1. HttpMessageConverter 的作用是什么?为什么它是 Restful 流程的关键组件?

• 核心解答:HttpMessageConverter 是 Spring MVC 的"数据格式转换器",核心作用是"在 Java 对象和 HTTP 消息流之间做转换":一方面能将 Handler 返回的 Java 对象(如 User、List)转换成 HTTP 响应流支持的格式(如 JSON、XML);另一方面也能将前端传的 HTTP 请求流(如 JSON 字符串)转换成 Java 对象(如 User),是前后端数据交互的"桥梁"。

• 思考理解:HttpMessageConverter 解决了"前后端数据格式不兼容"的问题------前端只能识别 JSON、XML 等字符串格式,后端用 Java 对象存储数据,两者"语言不通";有了 HttpMessageConverter,就像有了"翻译官",自动完成"Java 对象→JSON"和"JSON→Java 对象"的转换,开发者不用手动写转换代码(比如手动用 JSON 工具类转对象),大幅减少重复工作。

• 生活例子:类比"国际学生和中文老师的翻译官"------国际学生(前端)只会说英语,中文老师(后端)只会说中文:① 学生用英语问"作业截止时间是什么时候"(前端传 JSON 字符串),翻译官(HttpMessageConverter)把英语翻译成中文(转成 Java 对象),老师能看懂;② 老师用中文回答"下周五截止"(后端返回 Java 对象),翻译官再把中文翻译成英语(转成 JSON 字符串),学生能看懂。没有翻译官,两者无法沟通,就像前后端没有 HttpMessageConverter 无法传输数据。

• 实际开发注意点:Spring Boot 会自动装配常用的 HttpMessageConverter,比如 MappingJackson2HttpMessageConverter(处理 JSON 格式,依赖 Jackson 依赖)、StringHttpMessageConverter(处理字符串格式);若需支持 XML 格式,可引入 JAXB 依赖,Spring 会自动装配对应的 HttpMessageConverter;若需自定义转换规则(如特殊枚举类型转换),可实现 HttpMessageConverter 接口编写自定义转换器,再注册到 Spring 容器中。

相关推荐
llwszx2 分钟前
【Java/Go后端手撸原生Agent(第五篇):多工具并行调用 + BashTool执行引擎 + Judge证据链升级】
java·后端·golang·状态机·pydantic·agnet·llm-as-judge
奈何不吃鱼3 分钟前
【SpringBoot】业务多线程四大实战场景
java·spring boot·多线程
野生风长13 分钟前
c++类和对象(this指针,重载operator,习题总结)
java·开发语言·c++
最后的最后、79614 分钟前
SQLi-Labs 六关 SQL 注入过关笔记
数据库·笔记·sql
霸道流氓气质23 分钟前
基于 Spring 事务同步机制的事务后置动作收集器 Starter 实践
java·后端·spring
筱谙24 分钟前
BES BLE CTKD 完整学习笔记
笔记·学习
会编程的土豆28 分钟前
数据库mysql八股
数据库·笔记·八股
过期动态28 分钟前
【LeetCode 热题 100】找到字符串中所有字母异位词
java·数据结构·算法·leetcode·职场和发展·rabbitmq
数据皮皮侠AI29 分钟前
退市监督数据(2000-2024)
大数据·人工智能·笔记·机器学习·回归
刘小八1 小时前
Spring AI Tool Calling 生产化:参数校验、权限控制与超时隔离
java·人工智能·spring