SpringMVC工做流程

1、springMVC是什麼?

​ springMVC是一個MVC的開源框架,springMVC就至關因而Struts2加上sring的整合,那麼springMVC和spring是什麼樣的關係呢?在百度百科上有一個很好的解釋:springMVC是spring的一個後續產品,其實就是spring在原有基礎上,又提供了web應用的MVC模塊,能夠簡單的把springMVC理解爲是spring的一個模塊(相似AOP,IOC這樣的模塊),網絡上常常會說springMVC和spring無縫集成,其實springMVC就是spring的一個子模塊,因此根本不須要同spring進行整合。html

​ 工做原理圖:前端

能夠看到這裏分爲大體11個步驟,這11個步驟的任務是這樣的:java

​ 一、用戶發送請求至前端控制器DispatcherServlet。web

​ 二、 DispatcherServlet收到請求調用HandlerMapping處理器映射器。spring

​ 三、 處理器映射器找到具體的處理器(能夠根據xml配置、註解進行查找),生成處理器對象及處理器攔截器(若是有則生成)一併返回給DispatcherServlet。apache

​ 四、DispatcherServlet調用HandlerAdapter處理器適配器。後端

​ 五、 HandlerAdapter通過適配調用具體的處理器(Controller,也叫後端控制器)。api

​ 六、Controller執行完成返回ModelAndView。網絡

​ 七、 HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet。架構

​ 八、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。

​ 九、 ViewReslover解析後返回具體View,這個view不是完整的,僅僅是一個頁面(視圖)名字,且沒有後綴名。

​ 十、DispatcherServlet根據View進行渲染視圖(即將模型數據填充至視圖中)。

​ 十一、 DispatcherServlet響應用戶。

圖中能夠看到,DispatcherServlet(前端控制器)佔據了很大的一部分,事實也是這樣,springMVC中,DispatcherServlet是他的核心。

接下來再看一下springMVC組件及其核心步驟的說明:

​ 黃色字體和綠色字體是對組件做用的說明,其中黃色字體說明的組件是框架提供,綠色字體說明的部分是要由工程師實現,紅色字體是核心架構的具體流程步驟

2、配置文件的方式結合源碼,瞭解工做流程

看完了原理,再來經過註釋的方式,寫一個Hello World,熟悉一下過程。

準備maven的web工程

maven須要的相關依賴,springMVC須要的spring-webmvc,日誌相關的slf4j-log4j12,JSP相關的jstl、servlet-api、jsp-api。

配置web.xml

由於DispatcherServlet自己就是一個Servlet,因此要在web.xml配置:

<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
複製代碼

建立springmvc配置文件

前端控制器要協調各個組件幹活,因此就要依賴於配置文件,SpringMVC要讀取的配置文件是要是本身手動建立,怎麼建立?配置文件應該怎麼命名?先來到DispatcherServlet的源代碼中:

能夠看到DispatcherServlet繼承了FrameworkServlet,FrameworkServlet是Spring web框架的基本servlet。爲集成提供了基於javabean的總體解決方案中的Spring應用程序上下文。FrameworkServlet註釋中有這樣一段描述:

大體意思就是,默認的SpringMVC配置文件名字是「servlet-name」-servlet.xml, 而這個「servlet-name」就是在web.xml中配置的的名字,這裏就是springmvc,固然你也能夠起其餘名字。而後讀取的默認位置是在/WEB-INF/「servlet-name」-servlet.xml,因此這裏要在WEB-INF下面建立的是名叫springmvc-servlet.xml的配置文件,由於他和Spring都是一個體系內的,因此能夠直接建立spring的配置文件模板:

​ 如今有了配置文件,那麼改在配置文件中配置什麼東西?能夠回到SpringMVC工做流程圖看到,在springMVC配置文件中起碼要配置,映射器HandlerMapping、適配器HandelAdapter、處理器Handel(Controller)、視圖解析器ViewResolver。View的渲染不是SpringMVC來完成,因此這裏不須要配置。

配置映射器

​ 先來配置HandlerMapping,找到HandlerMapping,他是一個接口,因此要配置的是HandlerMapping的實現類,找到HandlerMapping源碼,查看他的繼承樹:

不看已通過時的(這裏Spring基於4.3的一個版本),咱們要經過請求中的url和HandlerMapping找處處理器,因此使用BeanNameUrlHandlerMapping,類名中的BeanName也就是要找的處理器,在註釋中也有說明,若是url是/foo ,對應的處理器名字也是/foo,假設咱們等等要訪問的url是localhost:8080/hello.do,那麼後面咱們再寫 處理器中的代碼的名字也是hello.do.

而後再springmvc-servler.xml中配置映射器:

<!--HandelMapping-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
複製代碼

配置適配器

​ 映射器處理完後,返回執行鏈,DispatcherServlet去調用處理器,處理器實現自己就就是多元化的,要根據處理器的具體實現,經過適配器(處理器包裝後)調用處理器,咱們先找到HandlerAdapter,看看這個接口的繼承樹:

有一個適配器SimpleControllerHandlerAdapter,可以幫咱們調用處理器(也能夠叫Controller)中的方法,

那麼他是怎麼調用處理器方法?

他是經過判斷你的處理器是否屬於Controller的類型,是則返回true。那麼Controller又是什麼呢?查看源代碼發現Controller是一個接口,也就意味着,咱們寫處理器部分的代碼要實現這一個接口。

這個接口中就一個方法,也就是處理器方法,這個方法等同與Servlet中的doGet/doPost方法。

咱們調用處理器方法的前提是實現Controller接口,在交給適配器,適配器判斷完以後,處理器(handler)在調用Controller接口中的處理器方法,因此最終調用處理器方法返回ModelAndView的是適配器的handler方法:

接下來咱們要作的事就是在springmvc-servlet.xml配置這個SimpleControllerHandlerAdapter:

<!--SimpleControllerHandlerAdapter-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
複製代碼

建立處理器

配置好適配器,按照流程圖接下來搞配置處理器,前面說提處處理器部分是咱們本身來實現的。

咱們在項目中建立一個一個包com.ljm.springmvc.controller,而後在包中建立處理器HelloController。這裏不叫包名類名不叫Handler而叫controller,至於爲何,多是由於他要實現一個接口,這接口叫Controller。而後重寫Controller中的方法:

package com.ljm.springmvc.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}
複製代碼

配置處理器

由於咱們本身建立了處理器和Spring沒啥關係,要想有有點什麼關係,就要把它配置到springmvc-servlet.xml中,處理器有不少個,那麼就要給他配上id或者name,這裏給他配置name,前面在配置映射器時提到,這個名字是咱們要訪問的url因此,不能隨便配:

<!--處理器,注意/不能丟-->
<bean name="/hello.do" class="com.ljm.springmvc.controller.HelloController" />
複製代碼

實現處理器

建立配置好處理器後,就要開始實現處理器中的業務,該調用哪一個service層就調用哪一個service,而後把結果響應到客戶端,這裏響應回去的是一個ModelAndView,這裏不實現service和dao層,寫一個死數據,無論三七二十一,先建立一個ModelAndView對象用於返回,

這裏能夠看到modelAndView有一些add方法:addObject(),根據參數能夠聯想到request的get/set Attribute方法,先設置一對key/value;但這時候只設置了數據,沒有告訴他往哪一個頁面返回,因此這裏還有一個操做,叫設置視圖名稱,使用的是modelAndView的setViewName方法,但這裏參數僅僅是設置要返回到的視圖名稱(邏輯視圖),且不帶後綴名,這裏咱們要返回到index.jsp,因此參數是index;因此處理器的代碼實現已經完成了:

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","spring MVC : Hello World!");
        modelAndView.setViewName("index");
        return modelAndView;
    }
}
複製代碼

配置視圖解析器

視圖解析器:ViewResolver是框架提供的,因此直接配置到springmvc-servlet.xml就行。

ViewResolver也是個接口,查看繼承樹,

其中有一個InternalResourceViewResolver,根據註釋咱們能夠看到咱們要用的就是他InternalResourceViewResolver繼承了UrlBasedViewResolver,根據UrlBasedViewResolver註釋的提示,咱們能夠看到視圖解析器正確的配置姿式:

咱們這裏的配置就應該是:

<!--視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
    <!--配置路徑:返回頁面在webapp下,因此配置/-->
    <property name="prefix" value="/" />
    <!--配置後綴名-->
    <property name="suffix" value=".jsp" />
    <!--viewname已經在處理器配置過了-->
</bean>
複製代碼

頁面接收返回參數

<html>
<body>
<h2>${msg}</h2>
</body>
</html>
複製代碼

添加日誌

添加log4j.properties 到resources

log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
複製代碼

測試

相關文章
相關標籤/搜索