SpringMVC的基本運行流程
先通過一張圖片來了解SpringMVC的基本流程
具體的執行流程:
- 客戶端向服務器端發送url請求,請求被前端控制器捕獲(通過Servlet-mapping中的url-pattern標籤設置)
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2. DispatcherServlet對請求URL進行解析,得到請求資源標識符(URI)。然後根據該URI,調用HandlerMapping獲得HandlerExecutionChain對象(包含了Handler對象以及Handler對象對應的攔截器)並返回。
3. DispatcherServlet 根據獲得的**Handler(對Controller的Bean本身和請求Method的包裝)**,選擇一個合適的HandlerAdapter。(**附註**:如果成功獲得HandlerAdapter後,此時將開始執行攔截器的preHandler(...)方法)
4. Handler執行完畢後會返回給前端控制器一個ModelAndView對象。
5. 根據返回的ModelAndView,選擇一個適合的ViewResolver(必須是已經註冊到Spring容器中的ViewResolver)來解析View對象並返回給前端控制器。
6. 根據view對象和model對象渲染前端頁面並返回給前端控制器。
7. 前端控制器返回頁面給客戶端。
通過一個簡單的例子來說明執行流程
1.index.jsp
<script>
top.location.href = "toLogin.do";
</script>
2.web.xml
<!-- 配置SpringMVC -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
jsp頁面發送toLogin.do的請求,前端控制器通過<url-pattern>*.do</url-pattern>
截取到請求,加載指定的配置文件springmvc-config.xml。
3.springmvc-config.xml
<!-- MVC註解驅動 -->
<mvc:annotation-driven/>
<!-- 配置掃描器,使得@Controller註解生效 -->
<context:component-scan base-package="com.ty.epms.controller" />
<!-- 定義視圖解析器 -->
<!-- prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前綴 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 後綴 -->
<property name="suffix" value=".jsp" />
</bean>
加載配置文件之後會掃描@Controller註解,<mvc:annotation-driven/>
註解方式配置處理器映射器和處理器適配器,也可以手動配置就和視圖解析器一樣。
4.UserController.java
@Controller
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
}
通過@RequestMapping("/toLogin")執行下面的方法,此時就已經返回了handler對象,接下來執行這個handler,我這裏並沒有設置Model對象,返回的是View(return “login”),這個過程會被試圖解析器解析這個view並渲染,然後通過DsipatcherServlet返回給客戶端。
Spring工作流程描述
1.爲什麼Spring只使用一個Servlet(DispatcherServlet)來處理所有請求?
詳細見J2EE設計模式-前端控制模式
2.Spring爲什麼要結合使用HandlerMapping以及HandlerAdapter來處理Handler?
符合面向對象中的單一職責原則,代碼架構清晰,便於維護,最重要的是代碼可複用性高。如HandlerAdapter可能會被用於處理多種Handler