1.Spring MVC的主要组件有哪些?
(1)DispatcherServlet:前端控制器,接收HTTP请求并将请求分发给对应的处理器
(2)HandlerMapping:处理器映射器,根据请求的URL路径,将请求映射到响应的处理器
(3)HandlerAdapter:处理器适配器,根据不同类型的处理器进行适配,使得DispatcherServlet可以调用不同类型的处理器进行处理
(4)Controller:控制器,用于处理请求并生成相应的响应
(5)ViewResolver:视图解析器,根据视图名字解析出相应的视图对象
(6)View:视图,负责渲染模型数据并产生响应的视图
2.Spring MVC的工作流程
(1)接收请求
客户端请求首先到达前端控制器 DispatcherServlet,它负责查询 HandlerMapping 获取执行链
(2)查找处理器
HandlerMapping 根据请求的 URL 查找对应的处理器(通常是 Controller 中的某个方法),并将处理器与可能的拦截器封装成一个 HandlerExecutionChain 对象,返回给 DispatcherServlet
(3)执行 Handler
DispatcherServlet 委托 HandlerAdapter 调用目标 Handler
(4)执行业务逻辑
被调用的 Handler(Controller 方法)根据请求参数执行业务逻辑,返回可能是 ModelAndView 对象、视图名称(String),或 @ResponseBody 返回数据(如 JSON)
(5)返回结果
HandlerAdapter 将结果(如 ModelAndView)返回给 DispatcherServlet
(6)视图解析与渲染
- 若返回视图:DispatcherServlet 使用视图解析器(ViewResolver)解析逻辑视图名为具体的视图对象,视图对象接收模型数据并渲染输出内容
- 若返回数据:HandlerAdapter 通过 HttpMessageConverter 转换数据(如 JSON),跳过视图渲染
(7)返回响应
DispatcherServlet 将渲染结果或返回的数据通过 HttpServletResponse 输出响应
3.Spring MVC的控制器是不是单例模式?
默认情况下,Spring MVC控制器是单例的,所有请求共享同一个实例
单例模式在多线程环境下可能导致线程安全问题
解决方法:
- 使用ThreadLocal来为每个线程提供独立的状态
- 使用@Scope("prototype")注解将控制器改为每个请求创建一个新的实例
- 使用@RequestScope注解或HttpServletRequest类确保请求相关状态是线程安全的
4.Spring MVC如何处理AJAX请求?
(1)添加 Jackson 依赖:自动转换 Java 对象为 JSON
(2)配置 JSON 转换器:确保 Spring 能将 Java 对象转为 JSON
(3)使用 @ResponseBody:控制器方法返回数据时,加 @ResponseBody 直接返回 JSON
(4)客户端通过 AJAX 获取数据:JavaScript 使用 fetch() 发送请求,并处理 JSON 响应
5.Spring和Spring MVC为什么需要父子容器?
父容器:管理业务逻辑和数据访问层(service、dao),配置在spring-cor.xml
子容器:管理Web层(controller),配置在spring-mvc.xml
父子容器关系:子容器可以访问父容器的对象,父容器无法访问子容器
优点:
- 避免Web层和核心层耦合
- 便于框架替换,只需要替换Web层的配置文件就可以将MVC框架替换成其他Web框架
6.是否可以把Spring MVC所有Bean都交给Spring容器来管理?
Spring MVC Bean 不应全交给父容器管理
原因:如果将所有Bean都交给父容器,Spring MVC初始化时,无法找到Controller的HandlerMethod(请求处理方法),因为它默认从子容器查找
导致结果:请求URL找不到对应的处理方法,产生错误404
正确做法:让Spring容器管理业务逻辑和数据层,让Spring MVC管理Web层,保持父子容器的分工和隔离
7.是否可以把Spring的Bean都交给Spring-mvc来管理?
可以将所有Bean都交给Spring MVC(子容器)管理,但不推荐
原因:子容器可以访问父容器,但父容器却不可以访问子容器;不推荐是因为若事务和AOP配置部分在父容器、部分在子容器,可能会导致事务失效或AOP无效
8.如何实现零配置的Spring MVC?原理是什么?
零配置 Spring MVC 的实现是通过 Servlet 3.0 规范和 Spring 的 ServletContainerInitializer 接口
省略 web.xml:Spring自动注册 ContextLoaderListener 和 DispatcherServlet
省略 spring.xml 和 spring-mvc.xml:通过继承 AbstractAnnotationConfigDispatcherServletInitializer 来替代 XML 配置文件,自动加载父子容器配置类
核心原理:通过 ServletContainerInitializer 接口动态注册容器,自动创建和配置父子容器,实现零配置
9.Spring MVC的拦截器和过滤器有什么区别?执行顺序?
过滤器:
- 依赖于servlet容器,对所有请求有效
- 不能直接访问容器中的Bean,除非是Spring管理的过滤器
- 执行顺序:DispatcherServlet 之前
拦截器:
- 不依赖于servlet容器,只对Spring MVC请求有效
- 可以访问容器中的Bean,支持依赖注入
- 执行顺序:请求到达控制器之前执行,控制器处理完请求后再次执行
这是我整理的笔记,目前还在学习阶段,文章中可能有错误和不足,欢迎大家斧正!