目錄
一、基于餐廳比喻的代碼示例 ,幫助你理解各組件間的協作關系
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 響應。
- 示例:服務員把宮保雞丁放在餐桌上,顧客看到色香味俱全的菜品。
- 示例:服務員把宮保雞丁放在餐桌上,顧客看到色香味俱全的菜品。
總結對比表
?
請求處理流程圖
