1. 程式人生 > >二、詳細架構

二、詳細架構

_id 處理請求 接收 發送請求 obj bject ride mvc架構 lsp

1、SpringMVC 詳細介紹

  通過入門實例,我們大概知道 SpringMVC 的作用,那麽它到底是什麽呢?

  Spring Web MVC是一種基於Java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,即使用了MVC架構模式的思想,將web層進行職責解耦,基於請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發,Spring Web MVC也是要簡化我們日常Web開發的。

  與之相反的是基於組件的、事件驅動的Web框架,如Tapestry、JSF等,在此就不介紹了。

  Spring Web MVC也是服務到工作者模式的實現,但進行可優化。前端控制器是DispatcherServlet;應用控制器其實拆為處理器映射器(Handler Mapping)進行處理器管理和視圖解析器(View Resolver)進行視圖管理;頁面控制器/動作/處理器為Controller接口(僅包含ModelAndView handleRequest(request, response) 方法)的實現(也可以是任何的POJO類);支持本地化(Locale)解析、主題(Theme)解析及文件上傳等;提供了非常靈活的數據驗證、格式化和數據綁定機制;提供了強大的約定大於配置(慣例優先原則)的契約式編程支持。

回到頂部

2、SpringMVC 處理請求流程

技術分享圖片

第一步:用戶發送請求到前端控制器(DispatcherServlet)。

第二步:前端控制器請求 HandlerMapping 查找 Handler,可以根據 xml 配置、註解進行查找。

第三步: 處理器映射器 HandlerMapping 向前端控制器返回 Handler

第四步:前端控制器調用處理器適配器去執行 Handler

第五步:處理器適配器執行 Handler

第六步:Handler 執行完成後給適配器返回 ModelAndView

第七步:處理器適配器向前端控制器返回 ModelAndView

    ModelAndView 是SpringMVC 框架的一個底層對象,包括 Model 和 View

第八步:前端控制器請求試圖解析器去進行視圖解析

    根據邏輯視圖名來解析真正的視圖。

第九步:試圖解析器向前端控制器返回 view

第十步:前端控制器進行視圖渲染

    就是將模型數據(在 ModelAndView 對象中)填充到 request 域

第十一步:前端控制器向用戶響應結果

下面我們對上面出現的一些組件進行解釋:

1 2 3 4 5 6 7 8 9 10 11 12 13 1、前端控制器DispatcherServlet(不需要程序員開發)。   作用:接收請求,響應結果,相當於轉發器,中央處理器。有了DispatcherServlet減少了其它組件之間的耦合度。
2、處理器映射器HandlerMapping(不需要程序員開發)。   作用:根據請求的url查找Handler。 3、處理器適配器HandlerAdapter(不需要程序員開發)。   作用:按照特定規則(HandlerAdapter要求的規則)去執行Handler。 4、處理器Handler(需要程序員開發)。   註意:編寫Handler時按照HandlerAdapter的要求去做,這樣適配器才可以去正確執行Handler 5、視圖解析器ViewResolver(不需要程序員開發)。   作用:進行視圖解析,根據邏輯視圖名解析成真正的視圖(view) 6、視圖View(需要程序員開發jsp)。   註意:View是一個接口,實現類支持不同的View類型(jsp、freemarker、pdf…) ps:不需要程序員開發的,需要程序員自己做一下配置即可。

  可以總結出:需要我們開發的工作只有處理器 Handler 的編寫以及視圖比如JSP頁面的編寫。可能你還對諸如前端控制器、處理器映射器等等名詞不太理解,那麽接下來我們對其進行詳細的介紹。

回到頂部

3、配置前端控制器

  在 web.xml 文件中進行如下配置:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SpringMVC_01</display-name> <!-- 配置前端控制器DispatcherServlet --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--springmvc.xml 是自己創建的SpringMVC全局配置文件,用contextConfigLocation作為參數名來加載 如果不配置 contextConfigLocation,那麽默認加載的是/WEB-INF/servlet名稱-servlet.xml,在這裏也就是 springmvc-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!--第一種配置:*.do,還可以寫*.action等等,表示以.do結尾的或者以.action結尾的URL都由前端控制器DispatcherServlet來解析 第二種配置:/,所有訪問的 URL 都由DispatcherServlet來解析,但是這裏最好配置靜態文件不由DispatcherServlet來解析 錯誤配置:/*,註意這裏是不能這樣配置的,應為如果這樣寫,最後轉發到 jsp 頁面的時候,仍然會由DispatcherServlet進行解析, 而這時候會找不到對應的Handler,從而報錯!!! --> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>

  

回到頂部

4、配置處理器適配器

  在 springmvc.xml 文件中配置。用來約束我們所需要編碼的 Handler類。

  第一種配置:編寫 Handler 時必須要實現 Controller

1 2 <!-- 配置處理器適配器,所有適配器都得實現 HandlerAdapter接口 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

  我們可以查看源碼: 技術分享圖片

  第二種配置:編寫 Handler 時必須要實現 HttpRequestHandler

1 2 <!-- 配置處理器適配器第二種方法,所有適配器都得實現 HandlerAdapter接口 ,這樣配置所有Handler都得實現 HttpRequestHandler接口--> <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />

  技術分享圖片

回到頂部

5、編寫 Handler

  在 springmvc.xml 文件中配置。通俗來講,就是請求的 URL 到我們這裏所編寫的 Handler 類的某個方法進行一些業務邏輯處理。

  我們在上面講解了兩個處理器適配器來約束 Handler,那麽我們就通過上面兩種配置分別編寫兩個 Handler

  第一種:實現Controller 接口

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.ys.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller{ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView modelView = new ModelAndView(); //類似於 request.setAttribute() modelView.addObject("name","張三"); modelView.setViewName("/WEB-INF/view/index.jsp"); return modelView; } }

  第二種:實現 HttpRequestHandler 接口

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.ys.controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.HttpRequestHandler; public class HelloController2 implements HttpRequestHandler{ @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("name", "張三"); request.getRequestDispatcher("/WEB-INF/view/index.jsp").forward(request, response); } }

  總結:通常我們使用第一種方式來編寫 Handler ,但是第二種沒有返回值,我們可以通過 response 修改相應內容,比如返回 json 數據。

1 2 3 response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json字符串");

  所以具體使用哪一種根據實際情況來判斷。

回到頂部

5、配置處理器映射器

  在 springmvc.xml 文件中配置。通俗來講就是請求的 URL 怎麽能被 SpringMVC 識別,從而去執行我們上一步所編寫好的 Handler

  第一種方法:

1 2 3 4 5 6 <!-- 配置Handler --> <bean name="/hello.do" class="com.ys.controller.HelloController2" /> <!-- 配置處理器映射器 將bean的name作為url進行查找,需要在配置Handler時指定bean name(就是url)--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

  這樣配置的話,那麽請求的 URL,必須為 http://localhost:8080/項目名/hello.do

  

  第二種方法:

1 2 3 4 5 6 7 8 9 10 11 12 <!-- 配置Handler --> <bean id="hello1" class="com.ys.controller.HelloController" /> <bean id="hello2" class="com.ys.controller.HelloController" /> <!-- 第二種方法:簡單URL配置處理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/hello1.do">hello1</prop> <prop key="/hello2.do">hello2</prop> </props> </property> </bean>

  這種配置請求的 URL可以為 http://localhost:8080/項目名/hello1.do,或者http://localhost:8080/項目名/hello2.do

總結:上面兩種處理器映射器配置可以並存,前端控制器會正確的去判斷 url 用哪個 Handler 去處理。

回到頂部

6、配置視圖解析器

  第一種配置:

1 2 3 <!-- 配置視圖解析器 進行jsp解析,默認使用jstl標簽,classpath下得有jstl的包--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

 如果這樣配,那麽在 Handler 中返回的必須是路徑+jsp頁面名稱+".jsp" 

  第二種配置:

1 2 3 4 5 6 7 <!--配置視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 返回視圖頁面的前綴 --> <property name="prefix" value="/WEB-INF/view"></property> <!-- 返回頁面的後綴 --> <property name="suffix" value=".jsp"></property> </bean>

  如果這樣配,那麽在 Handler 中只需要返回在 view 文件夾下的jsp 頁面名就可以了。

回到頂部

7、DispatcherServlet.properties

  上面我們講解了各種配置,可能有人會問這麽多配置,萬一少配置了一樣,那不就不能運行了,那我們能不能不配置呢?答案是肯定的,SpringMVC 給我們提供了一個 DispatcherServlet.properties 文件。系統會首先加載這裏面的配置,如果我們沒有配置,那麽就默認使用這個文件的配置;如果我們配置了,那麽就優先使用我們手動配置的。

  技術分享圖片

  在 SpringMVC 運行之前,會首先加載 DispatcherServlet.properties 文件裏面的內容,那麽我們來看看這裏面都是什麽。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # Default implementation classes for DispatcherServlet‘s strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

  我們可以從上面得出,如果我們不手動進行各種配置,那麽也有會默認的

  ①、處理器適配器默認:org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter

  ②、處理器映射器默認:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

  ③、視圖解析器默認:org.springframework.web.servlet.view.InternalResourceViewResolve

二、詳細架構