MVC模式css
1 用戶請求經過http請求到達前段控制器html
2 前端發給真正的控制器Controller前端
3 將處理以後的數據以model的格式進行返回java
4 前端控制器將model發送給View template(視圖模板)來進行解析和展現mysql
概念解析:web
前端控制器spring
MVC的本質:將業務數據抽取和業務數據呈現相分離sql
爲用戶提供UI,重點關注於數據的呈現express
業務數據的信息標示,關注支撐業務的信息構成,一般爲多個業務實體的組合。json
例如VO PO這些東西
調用業務邏輯產生合適的model,傳遞數據給視圖層用於呈現
DispatcherServlet便是前端控制器
就是調用業務邏輯的地方
@RequestMapping這個參數能夠用在Controller類上和方法上,定義url訪問到的類,或者精確到類當中的方法
若是須要在url當中添加參數,能夠有@RequestParam
須要在url當中添加參數可使用@RequestParam和@PathVariable兩種方法
傳統的servlet請求的形式
@RequestMapping 聲明訪問的URL。類和方法上都可使用
@RequestParam 形如xx/xxx?xx=xx的參數
@PathVariable 形如xx/xx/{xxxx}的參數
springMVC傳遞參數的三種方式:
1)使用參數註解@RequestParam
url形式:http://host:8080/courses/view?courseID=123
controller參數中傳入:@RequestParam("courseID") Integer courseID
2)使用路徑變量註解@PathVariable
url形式:http://host:8080/courses/view2/{courseID}方法的requestMapping:@RequestMapping(value="/view2/{courseID}",method=RequestMethod.GET)
controller參數中傳入:@PathVariable("courseID") Integer courseID
3)使用傳統的從HttpServletRequest獲取參數
url形式:http://host:8080/courses/view3?courseID=123
controller參數中傳入HttpServletRequest,使用request.getParameter("key")來獲取參數值。
HandlerAdapter至關於Controller 與DispatcherServle之間的橋樑。DispatcherServle調用HandlerAdapter來實現任務分發給相關的業務邏輯
攔截器,主要工做是在Handler調用以前,以後,以及view呈現後作一些事情
HandlerMapping主要用於確認DispatcherServlet和Controller之間的映射的類,主要是配置並告知DispatcherServlet由哪一個Controller來響應
HandlerExecutionChain
ModelAndView
ViewResolver:幫助DispatcherServlet找到對應的view
各個基本類的互相之間調用
1.web.xml:web項目的最基本的配置文件,全部框架監聽器、servlet都在此配置
1.1.web.xml是maven自動生成的使用的是2.3.dtd的標準,該標準默認關閉EL表達式,若是想使用EL表達式可使用2.4及以上的標準
<?xml version="1.0" encoding="UTF-8"?>
多個DispatcherServlet的狀況,服務不一樣羣體的請求的分發
<?xml version="1.0" encoding="UTF-8"?>
<!--使用2.4版本-->
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Study</display-name>
<!-- Spring應用上下文, 理解層次化的ApplicationContext -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/configs/spring/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--在針對若是要區分處理不一樣的用戶羣體時。可使用多個DispatcherServlet-->
<!-- DispatcherServlet, Spring MVC的核心 -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- DispatcherServlet對應的上下文配置, 默認爲/WEB-INF/$servlet-name$-servlet.xml
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/configs/spring/mvc-dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<!-- mvc-dispatcher攔截全部的請求-->
<!--指定不一樣的url的來源的劃分依據-->
<url-pattern>/</url-pattern>
<!--例如能夠定義其餘的劃分-->
<!--<url-pattern>/ws</url-pattern>-->
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<!--spring-mvc配置文件-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 本配置文件是供名爲mvc-dispatcher的DispatcherServlet使用, 提供其相關的Spring MVC配置 -->
<!-- 啓用Spring基於annotation的DI, 使用戶能夠在Spring MVC中使用Spring的強大功能。 激活 @Required
@Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等標註 -->
<context:annotation-config />
<!-- DispatcherServlet上下文, 只管理@Controller類型的bean, 忽略其餘型的bean, 如@Service -->
<context:component-scan base-package="com.imooc.mvcdemo">
<!--在本上下文當中,只對Controller這個註解的類進行加載-->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- HandlerMapping, 無需配置, Spring MVC能夠默認啓動。 DefaultAnnotationHandlerMapping
annotation-driven HandlerMapping -->
<!-- 擴充了註解驅動,能夠將請求參數綁定到控制器參數 -->
<mvc:annotation-driven />
<!-- 靜態資源處理, css, js, imgs -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!--一個DispatcherServlet當中能夠配置多個ViewResolver,可使用order來排序-->
<!-- 配置ViewResolver。 能夠用多個ViewResolver。 使用order屬性排序。 InternalResourceViewResolver放在最後。 -->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="htm" value="text/html" />
</map>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsps/" />
<property name="suffix" value=".jsp" />
</bean>
<!--200*1024*1024即200M resolveLazily屬性啓用是爲了推遲文件解析,以便捕獲文件大小異常 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="209715200" />
<property name="defaultEncoding" value="UTF-8" />
<property name="resolveLazily" value="true" />
</bean>
</beans>
引入依賴 jackson
在mvc-dispatcher-servlet當中添加jackson的配置
<?xml version="1.0" encoding="UTF-8"?>
<!--單純的spring的配置文件-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--此處加載的是spring的上下文,採用註解的方式進行上下文當中內容的注入-->
<!--激活注入的方式來進行service的注入-->
<context:annotation-config />
<context:component-scan base-package="com.imooc.mvcdemo">
<!--過濾掉Controller類型註解,告訴Spring的上下文管理沒必要管理被Controller註解的類了-->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>
首先選擇maven項目,以後在下拉表中勾選 apcahe的 webapp
填寫maven項目的GroupId以及ArtifactId
以後修改pom,在裏邊添加SpringMVC項目通常經常使用的maven依賴
一個pom.xml例子,主要的依賴有:
<!--針對普通的springMVC項目須要的jar-->
<!--servlet 核心的servlet引擎-->
<!--jsp 處理jsp的-->
<!--jstl 處理js的-->
<!--mysql-->
<!--spring-web-->
<!--spring-webmvc-->
若是須要其餘依賴,則能夠自行添加
1 DispatcherServlet:前端控制器
2 Controller:調用業務邏輯生成model的地方
3 HandlerAdapter:DispatcherServlet經過HandlerAdapter調用controller。在HandlerMapping返回處理請求的Controller實例後,須要一個幫助定位具體請求方法的處理類,這個類就是HandlerAdapter,HandlerAdapter是處理器適配器,Spring MVC經過HandlerAdapter來實際調用處理函數。例如Spring MVC自動註冊的AnnotationMethodHandlerAdpater,HandlerAdapter定義瞭如何處理請求的策略,經過請求url、請求Method和處理器的requestMapping定義,最終肯定使用處理類的哪一個方法來處理請求,並檢查處理類相應處理方法的參數以及相關的Annotation配置,肯定如何轉換須要的參數傳入調用方法,並最終調用返回ModelAndView。DispatcherServlet中根據HandlerMapping找到對應的handler method後,首先檢查當前工程中註冊的全部可用的handlerAdapter,根據handlerAdapter中的supports方法找到可使用的handlerAdapter。經過調用handlerAdapter中的handler方法來處理及準備handler method的參數及annotation(這就是spring mvc如何將request中的參數變成handle method中的輸入參數的地方),最終調用實際的handler method。
4 HandlerMapping:DispatcherServlet與Handler映射關係的類,在Spring3.0之後這個mapping默承認以不配置即採用annotation來掃描全部被@Controller關鍵字註解了的類。HandlerMapping
5 HandlerInterception:攔截器,主要是提供preHandle postHandle after三個方法,在調用controller先後使用
6 HandlerExecutionChain:preHandle->Controller method->postHandle->afterCompletion的執行鏈
7 ModelAndView:model的具體表現
8 ViewResolver:視圖解析器,決定採用那個視圖進行呈現
9 View:界面
具體時序圖
時序圖的解析
1 用戶向服務器發送http請求,此時請求被前端控制器DispatcherServlet捕獲
2 DispatcherServlet對請求的URL進行解析,得到請求資源的標識符URI。根據URI,調用HandlerMapping得到到Handler配置相關的全部對象(主要包括了Handler對象以及Handler對象的攔截器),最後以HandlerExecutionChain對象的形式返回
3 DispatcherServlet根據得到的Handler,選擇合適的HanlerAdapter。(若是獲取到HandlerAdapter以後,將開始執行攔截器preHandler()方法)
4 提取Request中的數據模型,填充Handler入參,開始執行Handle(Controller)。此時根據配置,Spring的額外動做:
1) HttpMessageConveter:將請求消息json、xml等轉換爲一個對象,將對象轉換爲指定的相應信息
2) 數據轉換:對請求消息進行數據轉換,例如將String轉換爲Integer、Double等
3) 數據格式化:對請求消息進行數據格式化,將字符串轉換爲格式化數字或者格式化日期
4) 數據驗證:驗證數據的有效性(長度、格式),驗證結果存儲到BindingResult或Error
5 Handler執行完成後,向DispatcherServlet返回一個ModelAndView對象
6 根據返回的ModelAndView,DispatcherServlet選擇合適的ViewResolver(必須是已經註冊到Spring容器中的ViewResolver)
7 ViewResolver結合Model和View來渲染視圖
8 將渲染結果返回給客戶端
Spring工做流程描述
爲何Spring只使用一個Servlet(DispatcherServlet)來處理全部請求?
詳細見J2EE設計模式-前端控制模式
Spring爲何要結合使用HandlerMapping以及HandlerAdapter來處理Handler?
符合面向對象中的單一職責原則,代碼架構清晰,便於維護,最重要的是代碼可複用性高。如HandlerAdapter可能會被用於處理多種Handler。
Handler不等於Controller,Handler包含Controller,緣由是@Controller註解是在Spring3.0 以後引入的。
HandlerMapping是用來找Handler(Controller)的,其默認去掃@Controller註解
而RequestMapping對應於將uri和Controller類及其中的方法對應。
處理器映射。它會根據某些規則將進入容器的請求映射到具體的處理器以及一系列前處理器和後處理器(即處理器攔截器)上。具體的規則視 HandlerMapping 類的實現不一樣而有所不一樣。其最經常使用的一個實現支持你在控制器上添加註解,配置請求路徑。固然,也存在其餘的實現。
處理器適配器。拿到請求所對應的處理器後,適配器將負責去調用該處理器,這使得 DispatcherServlet 無需關心具體的調用細節。比方說,要調用的是一個基於註解配置的控制器,那麼調用前還須要從許多註解中解析出一些相應的信息。所以, HandlerAdapter 的主要任務就是對 DispatcherServlet 屏蔽這些具體的細節。
處理器異常解析器。它負責將捕獲的異常映射到不一樣的視圖上去,此外還支持更復雜的異常處理代碼。
視圖解析器。它負責將一個表明邏輯視圖名的字符串(String)映射到實際的視圖類型 View 上。
地區解析器 和 地區上下文解析器。它們負責解析客戶端所在的地區信息甚至時區信息,爲國際化的視圖定製提供了支持。
主題解析器。它負責解析你web應用中可用的主題,好比,提供一些個性化定製的佈局等。
解析multi-part的傳輸請求,好比支持經過HTML表單進行的文件上傳等。