用戶協(xié)議通過(guò)http協(xié)議到達(dá)前端控制器,前端控制器判斷該有誰(shuí)來(lái)處理,將請(qǐng)求帶給controller(控制器),控制器了解業(yè)務(wù)處理邏輯細(xì)節(jié)(負(fù)責(zé)數(shù)據(jù)抽取),將業(yè)務(wù)邏輯生成數(shù)據(jù)返回給前端控制器,前端控制器再將業(yè)務(wù)邏輯分發(fā)給業(yè)務(wù)視圖,由業(yè)務(wù)視圖呈獻(xiàn)業(yè)務(wù)頁(yè)面,再將業(yè)務(wù)頁(yè)面返還給前端控制器,最終返還給客戶端。
MVC本質(zhì):MVC的核心思想是業(yè)務(wù)數(shù)據(jù)的抽取同業(yè)務(wù)數(shù)據(jù)呈現(xiàn)相分離。

SpringMVC框架介紹
Spring 框架提供了構(gòu)建 Web 應(yīng)用程序的全功能 MVC 模塊。使用 Spring 可插入的 MVC 架構(gòu),可以選擇是使用內(nèi)置的 Spring Web 框架還是 Struts 這樣的 Web 框架。通過(guò)策略接口,Spring 框架是高度可配置的,而且包含多種視圖技術(shù),例如 JavaServer Pages(JSP)技術(shù)、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的視圖,所以不會(huì)強(qiáng)迫您只使用 JSP 技術(shù)。
Spring MVC 分離了控制器、模型對(duì)象、分派器以及處理程序?qū)ο蟮慕巧@種分離讓它們更容易進(jìn)行定制
Spring的MVC框架主要由DispatcherServlet、處理器映射、處理器(控制器)、視圖解析器、視圖組成。
SpringMVC就是通過(guò)DispatcherServlet將一堆組件串聯(lián)起來(lái)的Web框架。
SpringMVC的原理

SpringMVC接口解釋
DispatcherServlet接口:
Spring提供的前端控制器,所有的請(qǐng)求都有經(jīng)過(guò)它來(lái)統(tǒng)一分發(fā)。在DispatcherServlet將請(qǐng)求分發(fā)給Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具體的Controller。
HandlerAdapter接口:
HandlerAdapter相當(dāng)于controller,DispatcherServelet調(diào)用各種HandlerAdapter來(lái)實(shí)現(xiàn)任務(wù)分發(fā)給相關(guān)的業(yè)務(wù)邏輯。
HandlerInterceptor:
HandlerInterceptor是一個(gè)接口,可以用來(lái)在Handler調(diào)用之前、之后,以及view呈現(xiàn)后可以做很多事情。
HandlerMapping接口:
HandlerMapping是負(fù)責(zé)確定DispatcherServelet與controller之間映射的類(lèi),告訴DispatcherServelet,在請(qǐng)求到來(lái)后,由哪個(gè)controller來(lái)響應(yīng)這個(gè)請(qǐng)求。
Controller接口:
Controller將處理用戶請(qǐng)求,這和Struts Action扮演的角色是一致的。一旦Controller處理完用戶請(qǐng)求,則返回ModelAndView對(duì)象給DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和視圖(View)。
ViewResolver接口:
Spring提供的視圖解析器(ViewResolver)在Web應(yīng)用中查找View對(duì)象,從而將相應(yīng)結(jié)果渲染給客戶。
SpringMVC運(yùn)行原理
客戶端請(qǐng)求提交到DispatcherServlet
由DispatcherServlet控制器查詢(xún)一個(gè)或多個(gè)HandlerMapping,找到處理請(qǐng)求的Controller
DispatcherServlet將請(qǐng)求提交到Controller
Controller調(diào)用業(yè)務(wù)邏輯處理后,返回ModelAndView
DispatcherServlet查詢(xún)一個(gè)或多個(gè)ViewResoler視圖解析器,找到ModelAndView指定的視圖
視圖負(fù)責(zé)將結(jié)果顯示到客戶端
DispatcherServlet是整個(gè)Spring MVC的核心。它負(fù)責(zé)接收HTTP請(qǐng)求組織協(xié)調(diào)Spring MVC的各個(gè)組成部分。其主要工作有以下三項(xiàng):
- 截獲符合特定格式的URL請(qǐng)求。
- 初始化DispatcherServlet上下文對(duì)應(yīng)的WebApplicationContext,并將其與業(yè)務(wù)層、持久化層的WebApplicationContext建立關(guān)聯(lián)。
- 初始化Spring MVC的各個(gè)組成組件,并裝配到DispatcherServlet中。
配置SpringMVC需要的配置文件
DispatcherServlet是整個(gè)Spring MVC的核心,SpringMVC所有的請(qǐng)求都會(huì)通過(guò)這個(gè)前端控制器。
我們可以根據(jù)需要配置一個(gè)或多個(gè)ApplicationContext,常見(jiàn)的做法是配置一個(gè)根ApplicationContext和一個(gè)前端ApplicationContext。前端ApplicationContext定義網(wǎng)絡(luò)相關(guān)的配置,根ApplicationContext配置數(shù)據(jù)庫(kù)等網(wǎng)絡(luò)無(wú)關(guān)的組件。這樣的話就需要web.xml寫(xiě)成類(lèi)似這樣的。
它配置的地方是在web.xml里面:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置全局的applicationContext -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 配置spring的核心servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--如果只需要一個(gè)ApplicationContext,值留空-->
<param-value>classpath:spring/dispatcher-servlet.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>
<!-- 該監(jiān)聽(tīng)器將在web容器啟動(dòng)時(shí)激活spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 處理有JavaBean、Introspector的使用而引起的緩沖泄露,建議配置此監(jiān)聽(tīng)器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 編碼過(guò)濾器 -->
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- session的有效時(shí)間 -->
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
配置的時(shí)候還指明了contextConfigLocation,這樣就會(huì)去加載這個(gè)applicationContext.xml了。
在上面的配置中,我們創(chuàng)建了兩個(gè)ApplicationContext,一個(gè)是全局的,另一個(gè)是前端控制器dispatcher-servlet使用的。
這里的ApplicationContext其實(shí)是一個(gè)WebApplicationContext,它可以配置一些網(wǎng)絡(luò)相關(guān)的組件,例如視圖解析器、異常解析器、主題解析器等等。
由于SpringMVC啟動(dòng)的時(shí)候會(huì)讀取WEB-INF/applicationContext.xml
所以要在WEB-INF下創(chuàng)建一個(gè)空的applicationContext。xml
配置視圖解析器
spatcherServlet控制器查詢(xún)一個(gè)或多個(gè)HandlerMapping,找到處理請(qǐng)求的Controller。這里其實(shí)是通過(guò)在dispatcher-servlet.xml配置了掃描路徑以及開(kāi)啟了注解驅(qū)動(dòng)來(lái)實(shí)現(xiàn)的。
dispatcher-servlet.xml中的配置:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="viewResolver"
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>
<!-- 指定讓Spring的DispatcherServlet作為默認(rèn)Servlet,這樣我們就可以讓Spring處理根路徑/的請(qǐng)求了。
如果不加這個(gè),那么根路徑的請(qǐng)求默認(rèn)會(huì)由服務(wù)器來(lái)處理。 -->
<mvc:default-servlet-handler/>
<!-- 啟用MVC的注解支持。如果不添加這個(gè),那么我們就需要在XML文件中為每個(gè)控制器寫(xiě)一個(gè)Bean配置 -->
<mvc:annotation-driven/>
<!-- 用來(lái)掃描指定的路徑下的包,告訴Spring從哪里搜索注解來(lái)加載組件用的 -->
<context:component-scan base-package="com.meng"/>
</beans>
context:component-scan說(shuō)明了要掃描com.meng.demo這個(gè)包下所有的類(lèi)。
這里要注意一下,在開(kāi)發(fā)中有用到注解的類(lèi)一定都要在這個(gè)demo包下,不然就會(huì)拋異常的。
加載了掃描路徑后,還要開(kāi)啟注解驅(qū)動(dòng),這樣才能認(rèn)到代碼中使用到的注解,,比如@Controller這個(gè)注解。
<mvc:annotation-driven />
ViewResoler視圖解析器對(duì)應(yīng)配置里面的
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前綴 -->
<property name="prefix" value="/WEB-INF/pages/"/>
<!-- 后綴 -->
<property name="suffix" value=".jsp"/>
</bean>
這樣,當(dāng)controller中方法返回的是
return "index";
的時(shí)候,實(shí)際是指向了/WEB-INF/pages/index.jsp這個(gè)頁(yè)面。
上面的配置可以使用mvc命名空間簡(jiǎn)化。我們可以使用如下的配置替代上面的視圖解析器配置。
<mvc:view-resolvers>
<mvc:jsp view-class="org.springframework.web.servlet.view.JstlView"
prefix="/WEB-INF/jsp/"
suffix=".jsp"/>
</mvc:view-resolvers>
創(chuàng)建Controller
package com.meng;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/mvc")
public class MainController {
@RequestMapping(value = "/index")
public String index(Model model) {
model.addAttribute("name", "李帆");
return "index";
}
}
啟動(dòng)服務(wù)器訪問(wèn) http://localhost:8080/mvc/index
