1. 程式人生 > >(二)SpringMVC之執行的過程

(二)SpringMVC之執行的過程

服務器 上傳 執行過程 gin 開始 throw pack 獲取 type

技術分享圖片

(DispatcherServlet在Spring當中充當一個前端控制器的角色,它的核心功能是分發請求。請求會被分發給對應處理的Java類,Spring MVC中稱為Handle。)

① 用戶把請求發送給DispatcherServlet服務器。

DispatcherServlet對請求的URL(統一資源定位符)進行解析,得到URI(請求資源標識符)。然後根據該URI,調用HandlerMapping獲取該Handler配置的所有相關的對象,包括Handler對象以及Handler對象對應的攔截器,這些對象會被封裝到一個HandlerExecutionChain對象當中返回。

③ DisptcharServlet會根據獲得的Handler選擇一個合適的HandlerAdapter

。HandlerAdapter會被用於處理多種Handler,調用Handler實際處理請求的方法。

④ 提取請求中的模型數據,開始執行Handler(Controller類)。在填充Handler的入參過程中,根據配置,Spring可以做消息轉換、數據轉換、數據格式化、數據驗證的工作。

⑤ Handler執行完成後,想DispatcherServlet發送一個ModelAndView對象,ModelAndView對象中應該包含視圖名或視圖名和模型。

⑥ 根據返回的ModelAndView對象,選擇一個合適的ViewResolver(視圖解析器)返回給DispatcherServlet。

⑦ ViewResolver結合Model和View來渲染視圖。

⑧ 將視圖渲染結果返回給客戶端。

我們可以看到,DispatcherServlet在這個執行過程中是一位大哥的角色,為森麽它會坐穩大佬的位置呢?我們可以看它的源碼:

         protected void initStrategies(ApplicationContext context) {

                   initMultipartResolver(context);  //初始化上傳文件解析器

                   initLocaleResolver(context);  
//初始化本地解析器 initThemeResolver(context); // 初始化主體解析器 initHandlerMappings(context); //初始化處理器映射器,將請求映射到處理器 initHandlerAdapters(context); //初始化處理器適配器 initHandlerExceptionResolvers(context); //初始化處理異常解析器,如果執行過程中遇到異常將交給HandlerExceptionResolver來解析 initRequestToViewNameTranslator(context); //初始化請求到視圖名稱解析器 initViewResolvers(context); //初始化視圖解析器,通過ViewResolver解析邏輯視圖名到具體視圖實現 initFlashMapManager(context); //初始化flash映射管理器 }

接下來我們來看一下,整個流程的實現是怎麽樣的。

代碼實現:

① 引入spirng-framework的相關包和commons-logging包(WEB-INF/lib)。

② 在WEB-INF下的web.xml中進行配置(WEB-INF/web.xml):

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

id="WebApp_ID" version="3.1">

<!-- 定義Spring MVC的前端控制器 -->

         <servlet>

                   <!-- 配置前端控制器 -->

                   <!-- DispatcherServlet在Spring當中充當一個前端控制器的角色,它的核心功能是分發請求。

                            請求會被分發給對應處理的Java類,Spring MVC中稱為Handle

                    -->

           <!—配置一個名為springmvc的DispatcherServlet服務器 -->

                   <servlet-name>springmvc</servlet-name>

                   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

                   <init-param>

                            <!-- 定位spring mvc的配置文件 -->

                            <param-name>contextConfigLocation</param-name>

                            <param-value>/WEB-INF/springmvc-config.xml</param-value>

                   </init-param>

                   <load-on-startup>1</load-on-startup>

         </servlet>

         <!-- 讓Spring mvc的前端控制器攔截所有請求 -->

         <servlet-mapping>

                   <servlet-name>springmvc</servlet-name>

                   <url-pattern>/</url-pattern>

         </servlet-mapping>

</web-app>

 

③ 編寫SpringMVC的配置文件,在WEB-INF下的springmvc-config.xml。(WEB-INF/springmvc-config.xml)

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.2.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-4.2.xsd"> 

<!-- 配置handler,映射"/hello",或者可以直接在Controller類註解 -->

<bean name="/hello" class="org.fkit.controller.HelloController"/>

<!-- spring可以自動去掃描base-pack下面的包或者子包下面的Java文件

         ,如果掃描到有Spring的相關註解的類,則把這些類註冊為Spring的bean

-->

<context:component-scan base-package="org.fkit.controller" />

<!-- 處理映射器將bean的name作為url進行查找,需要在配置Handle時指定name(即url) -->

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- SimpleControllerHandlerAdapter是一個處理器適配器,所有處理適配器都要實現HandlerAdapter接口 -->

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

<!-- 視圖解析器 -->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>

</beans>

④ Controller的實現,用於處理請求(org.fkit.controller.HelloController)。

package org.fkit.controller;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.mvc.Controller;


public class HelloController implements Controller{

         private static final Log logger = LogFactory.getLog(HelloController.class);

         public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

                   logger.info("handleRequest 被調用");

                   //創建準備返回的ModelAndView對象,該對象通常包含了返回視圖名、模型的名稱以及模型對象

                   ModelAndView mv = new ModelAndView();

                   //添加模型數據,可以是任意的POJO對象

                   mv.addObject("message","HelloWorld");

                   //設置邏輯視圖名,視圖解析器會根據該名字解析到具體的試圖頁面

                   mv.setViewName("/WEB-INF/content/welcome.jsp");

                   //返回ModelAndView對象

                   return mv;

         }

}

 

⑤ 編寫視圖頁面,用於顯示已經處理好的View和Model的視圖渲染(WEB-INF/content/welcome.jsp)。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"

    pageEncoding="ISO-8859-1"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>Insert title here</title>

</head>

<body>

         ${requestScope.message }

</body>

</html>

(二)SpringMVC之執行的過程