目录
一、基于餐厅比喻的代码示例 ,帮助你理解各组件间的协作关系
1. DispatcherServlet 配置(服务员)
2. HandlerMapping 配置(菜单索引)
3. Controller 实现(厨师)
4. Service 层(厨房)
5. ViewResolver 配置(餐桌索引)
6. View 视图(餐桌)
7. 客户端请求流程(顾客点餐)
二、SpringMVC 底层原理与餐厅运作流程的类比
1. 客户端请求(顾客点餐)
2. DispatcherServlet 接收请求(服务员接单)
3. HandlerAdapter 调用 Controller(服务员传达厨师)
4. Controller 处理请求(厨师做菜)
5. ModelAndView 返回结果(厨师上菜)
6. ViewResolver 解析视图(服务员找餐桌)
7. View 渲染数据(摆盘上菜)
总结对比表
请求处理流程图
引言:以下我将MVC的底层各个流程比作一个餐厅的运作流程,这样便于我们理解。
一、基于餐厅比喻的代码示例 ,帮助你理解各组件间的协作关系
1. DispatcherServlet 配置(服务员)
// 在web.xml中配置DispatcherServlet(SpringBoot中自动配置)
<servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
2. HandlerMapping 配置(菜单索引)
<!-- spring-mvc.xml 配置HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
3. Controller 实现(厨师)
@Controller
@RequestMapping("/food")
public class FoodController {@Autowiredprivate FoodService foodService; // 厨房(Service层)// 处理 "/food/123" 请求(宫保鸡丁)@GetMapping("/{id}")public ModelAndView getFood(@PathVariable("id") Long id) {// 从厨房获取菜品(调用Service)Food food = foodService.getFoodById(id);// 返回视图名称和数据(餐盘+菜品)ModelAndView mav = new ModelAndView("foodDetail");mav.addObject("food", food);return mav;}
}
4. Service 层(厨房)
@Service
public class FoodServiceImpl implements FoodService {@Autowiredprivate FoodRepository foodRepository; // 食材库(DAO)@Overridepublic Food getFoodById(Long id) {// 从食材库获取食材,制作菜品return foodRepository.findById(id).orElseThrow(() -> new RuntimeException("菜品不存在"));}
}
5. ViewResolver 配置(餐桌索引)
<!-- spring-mvc.xml 配置ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/" /><property name="suffix" value=".jsp" />
</bean>
6. View 视图(餐桌)
<!-- /WEB-INF/views/foodDetail.jsp -->
<html>
<head><title>${food.name}</title>
</head>
<body><h1>菜品详情:${food.name}</h1><p>价格:${food.price} 元</p><p>配料:${food.ingredients}</p><img src="${food.imageUrl}" alt="${food.name}">
</body>
</html>
7. 客户端请求流程(顾客点餐)
-
顾客请求:访问
http://localhost:8080/food/123
-
DispatcherServlet 接收到请求,通过
RequestMappingHandlerMapping
找到FoodController.getFood()
方法。 -
Controller 调用
FoodService
获取菜品数据。 -
Controller 返回
ModelAndView("foodDetail", {food: 宫保鸡丁})
。 -
DispatcherServlet 通过
InternalResourceViewResolver
解析视图为/WEB-INF/views/foodDetail.jsp
。 -
JSP 将菜品数据渲染为 HTML 响应给客户端。
二、SpringMVC 底层原理与餐厅运作流程的类比
1. 客户端请求(顾客点餐)
- 顾客(客户端)进入餐厅(Web 应用),向服务员(DispatcherServlet)点餐(发送请求)。
- 示例:顾客说:“我要一份宫保鸡丁!”(对应 URL 请求 /food/123)。
2. DispatcherServlet 接收请求(服务员接单)
- 服务员(DispatcherServlet)收到订单后,首先查看菜单索引(HandlerMapping),确定由哪位厨师(Controller)负责制作这道菜。
- HandlerMapping:将 URL 请求映射到具体的 Controller 方法。
- 示例:菜单显示 “宫保鸡丁 → 川菜厨师”。
3. HandlerAdapter 调用 Controller(服务员传达厨师)
- 服务员(DispatcherServlet)通过对讲机(HandlerAdapter)通知川菜厨师(Controller)制作宫保鸡丁。
- HandlerAdapter:负责调用 Controller 方法并获取返回值。
- 示例:服务员说:“厨师,麻烦做一份宫保鸡丁!”
4. Controller 处理请求(厨师做菜)
- 川菜厨师(Controller)根据订单(请求参数),从厨房(Service/DAO)获取食材(数据),制作宫保鸡丁(处理业务逻辑)。
- Controller:处理请求,调用 Service 层获取数据,并返回一个视图名称(如 foodDetail)和模型数据(如菜品详情)。
- 示例:厨师从冰箱取鸡肉、花生,烹饪后装盘。
5. ModelAndView 返回结果(厨师上菜)
- 厨师(Controller)将做好的菜(Model 数据)放在餐盘(ViewName)上,交给服务员(DispatcherServlet)。
- ModelAndView:包含视图名称和模型数据。
- 示例:厨师说:“宫保鸡丁做好了,放在 3 号桌对应的餐盘上!”
6. ViewResolver 解析视图(服务员找餐桌)
- 服务员(DispatcherServlet)根据餐盘编号(ViewName),通过餐桌索引(ViewResolver)找到对应的餐桌(View)。
- ViewResolver:将视图名称映射到具体的视图实现(如 JSP、Thymeleaf)。
- 示例:服务员查看索引表:“3 号桌 → 大厅东侧靠窗位置”。
7. View 渲染数据(摆盘上菜)
- 服务员(DispatcherServlet)将菜(Model 数据)摆放在指定餐桌(View)上,顾客(客户端)看到最终的菜品(HTML 页面)。
- View:将模型数据填充到模板中,生成 HTML 响应。
- 示例:服务员把宫保鸡丁放在餐桌上,顾客看到色香味俱全的菜品。
- 示例:服务员把宫保鸡丁放在餐桌上,顾客看到色香味俱全的菜品。
总结对比表
请求处理流程图
