Model(模型):數據模型,提供要展現的數據,所以包含數據和行爲,能夠認爲是領域模型或 JavaBean 組件(包含數據和行爲),不過如今通常都分離開來:Value Object(數據) 和 服務層(行爲)。也就是模型提供了模型數據查詢和模型數據的狀態更新等功能,包括數據和業務。html
View(視圖):負責進行模型的展現,通常就是咱們見到的用戶界面,客戶想看到的東西。前端
Controller(控制器):接收用戶請求,委託給模型進行處理(狀態改變) ,處理完畢後把返回的模型數據返回給視圖,由視圖負責展現。 也就是說控制器作了個調度員的工做。java
執行步驟以下:web
1)首先用戶發送請求————>前端控制器,前端控制器根據請求信息(如 URL)來決定選擇哪個頁面控制器進行處理並把請求委託給它;上圖中的 一、2 步驟;spring
2)頁面控制器接收到請求後,進行功能處理,首先須要收集和綁定請求參數到一個對象,並進行驗證,而後將該對象對象委託給業務對象進行處理;處理完畢後返回一個 ModelAndView(模型數據和邏輯視圖名) ;上圖中的 三、四、5 步驟;設計模式
3)前端控制器收回控制權,而後根據返回的邏輯視圖名,選擇相應的視圖進行渲染,並把模型數據傳入以便視圖渲染;上圖 中的步驟 六、7;瀏覽器
4)前端控制器再次收回控制權,將響應返回給用戶,圖 2-1 中的步驟 8;至此整個結束。spring-mvc
具體流程步驟:tomcat
1)首先用戶發送請求——>DispatcherServlet,前端控制器收到請求後本身不進行處理,而是委託給其餘的解析器進行處理,做爲統一訪問點,進行全局的流程控制;服務器
2)DispatcherServlet——>Handlermapping(請求處處理器的映射),HandlerMapping 將會把請求映射爲 HandlerExecutionChain 對象(包含一個 Handler 處理器(頁面控制器)對象、多個 HandlerInterceptor 攔截器)對象,經過這種策略模式,很容易添加新的映射策略;
3)DispatcherServlet——>HandlerAdapter,HandlerAdapter 將會把處理器包裝爲適配器,從而支持多種類型的處理器,即適配器設計模式的應用,從而很容易支持不少類型的處理器;
4)HandlerAdapter——>處理器功能處理方法的調用,HandlerAdapter 將會根據適配的結果調用真正的處理器的功能處理方法,完成功能處理;並返回一個 ModelAndView 對象(包含模型數據、邏輯視圖名);
5)ModelAndView 的邏輯視圖名——> ViewResolver, ViewResolver 將把邏輯視圖名解析爲具體的 View,經過這種策略模式,很容易更換其餘視圖技術;
6)View——>渲染,View 會根據傳進來的 Model 模型數據進行渲染,此處的 Model 實際是一個 Map 數據結構,所以很容易支持其餘視圖技術;
7)返回控制權給 DispatcherServlet,由 DispatcherServlet 返回響應給用戶,到此一個流程結束。
在web.xml中添加
<!--前端控制器--> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!--參數定義了要裝入的 Spring 配置文件。--> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 當值爲0或者大於0時,表示容器在應用啓動時就加載這個servlet; 當是一個負數時或者沒有指定時,則指示容器在該servlet被選擇時才加載。 正數的值越小,啓動該servlet的優先級越高。 --> <load-on-startup>1</load-on-startup> </servlet>
在resources/spring-mvc.xml中配置handlerMapping、handlerAdapter
<!-- 非註解式控制器 --> <!-- 處理器映射解析器HandlerMapping --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 處理器適配器 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 處理器 --> <bean name="/hello" class="com.zfy.demo.springmvc.controller.HelloController"/> <!-- 註解式控制器 --> <!-- 開啓註解式處理器支持(啓用註解) 方式1 --> <!--bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>--> <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>--> <!-- 開啓註解式處理器支持(啓用註解) 方式2 --> <!--<mvc:annotation-driven />-->
在resources/spring-mvc.xml中配置viewResolver
<!-- 視圖分解器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
非註解式controller
public class HelloController implements Controller { public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { //一、收集參數 //二、綁定參數到命令對象 //三、調用業務對象 //四、選擇下一個頁面 ModelAndView mv = new ModelAndView(); //添加模型數據 能夠是任意的POJO對象 mv.addObject("message", "Hello World!"); //設置邏輯視圖名,視圖解析器會根據該名字解析到具體的視圖頁面 mv.setViewName("/hello"); return mv; }
ModelAndView:包含了視圖要實現的模型數據和邏輯視圖名;「mv.addObject("message", "Hello World!");」表示添加模型數據,此處能夠是任意 POJO 對象;「mv.setViewName("/hello");」表示設置邏輯視圖名爲「hello」,視圖解析器會將其解析爲具體的視圖,如前邊的視圖解析器InternalResourceVi。wResolver 會將其解析爲「WEB-INF/jsp/hello.jsp」。
註解式controller
@Controller public class HelloController2 { @RequestMapping(value = "/hello2") public ModelAndView hello(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { Map<String, Object> data = new HashMap<>(); data.put("message", "hello world 2"); return new ModelAndView("/hello", data); } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!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=UTF-8"> <title>Hello World</title> </head> <body> ${message} </body> </html>
運行步驟以下:
1)首先用戶發送請求 http://localhost:8080/hello——>web 容器,web 容器根據「/hello」路徑映射到DispatcherServlet(url-pattern 爲/)進行處理;
2) DispatcherServlet——>BeanNameUrlHandlerMapping 進行請求處處理的映射,BeanNameUrlHandlerMapping 將「/hello」路徑直接映射到名字爲「/hello」的 Bean 進行處理,即 HelloWorldController,BeanNameUrlHandlerMapping將其包裝爲HandlerExecutionChain(只包括 HelloWorldController 處理器,沒有攔截器) ;
3) DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter 將 HandlerExecutionChain中的處理器(HelloWorldController)適配爲 SimpleControllerHandlerAdapter;
4) SimpleControllerHandlerAdapter — — > HelloWorldController 處 理 器 功 能 處 理 方 法 的 調 用 ,SimpleControllerHandlerAdapter 將會調用處理器的 handleRequest 方法進行功能處理,該處理方法返回一個 ModelAndView 給 DispatcherServlet;
5)hello(ModelAndView 的邏輯視圖名)——>InternalResourceViewResolver, InternalResourceViewResolver 使用JstlView,具體視圖頁面在/WEB-INF/jsp/hello.jsp;
6) JstlView(/WEB-INF/jsp/hello.jsp)——>渲染,將在處理器傳入的模型數據(message=HelloWorld!)在視圖中展現出來;
7) 返回控制權給 DispatcherServlet,由 DispatcherServlet 返回響應給用戶,到此一個流程結束。
spring Web MVC 框架提供了 org.springframework.web.filter.CharacterEncodingFilter 用於解決 POST 方式形成的中文亂碼問題,具體配置以下:
<!-- 指定UTF-8編碼 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>