SpringMVC詳解(二)------詳細架構
通過上篇部落格,我們能編寫一個 SpringMVC 的入門例項,但是為什麼要這樣寫?這樣寫有啥好處?通過這篇部落格我們會有詳細的瞭解。
本篇部落格原始碼下載連結:http://pan.baidu.com/s/1boOfxlP 密碼:bxq4
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、前端控制器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 檔案中進行如下配置:
<?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" 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
<!-- 配置處理器介面卡,所有介面卡都得實現 HandlerAdapter介面 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
我們可以檢視原始碼:
第二種配置:編寫 Handler 時必須要實現 HttpRequestHandler
<!-- 配置處理器介面卡第二種方法,所有介面卡都得實現 HandlerAdapter介面 ,這樣配置所有Handler都得實現 HttpRequestHandler介面-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
5、編寫 Handler
在 springmvc.xml 檔案中配置。通俗來講,就是請求的 URL 到我們這裡所編寫的 Handler 類的某個方法進行一些業務邏輯處理。
我們在上面講解了兩個處理器介面卡來約束 Handler,那麼我們就通過上面兩種配置分別編寫兩個 Handler
第一種:實現Controller 介面
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 介面
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 資料。
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json字串");
所以具體使用哪一種根據實際情況來判斷。
5、配置處理器對映器
在 springmvc.xml 檔案中配置。通俗來講就是請求的 URL 怎麼能被 SpringMVC 識別,從而去執行我們上一步所編寫好的 Handler
第一種方法:
<!-- 配置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
第二種方法:
<!-- 配置Handler -->
<bean class="com.ys.controller.HelloController" />
<bean 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、配置檢視解析器
第一種配置:
<!-- 配置檢視解析器
進行jsp解析,預設使用jstl標籤,classpath下得有jstl的包-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
如果這樣配,那麼在 Handler 中返回的必須是路徑+jsp頁面名稱+".jsp"
第二種配置:
<!--配置檢視解析器 -->
<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 檔案裡面的內容,那麼我們來看看這裡面都是什麼。
# 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.InternalResourceViewResolver
相關文章
- MVC 三層架構案例詳細講解MVC架構
- iOS架構詳解iOS架構
- 詳細解讀!推薦演算法架構——召回演算法架構
- kafka核心架構詳解Kafka架構
- TDengine 3.0 架構詳解架構
- Chromium VIZ架構詳解架構
- Angular 4.0 架構詳解Angular架構
- Jenkins架構詳解Jenkins架構
- SpringMVC框架詳細教程(二)_建立動態Web專案SpringMVC框架Web
- springmvc註解詳解SpringMVC
- HotDB 基礎架構詳解架構
- 3.4 以太坊架構詳解架構
- Dubbo架構設計詳解架構
- Angular4.0架構詳解Angular架構
- 詳解安卓架構入門安卓架構
- Flink 的執行架構詳細剖析架構
- RabbitMQ架構詳解(7大架構原理模型圖解)MQ架構模型圖解
- iOS VIPER架構實踐(二):VIPER詳解與實現iOS架構
- Facebook移動架構:Android Flux架構詳解架構AndroidUX
- SpringMVC工作流程 --通透較詳細SpringMVC
- SpringMVC工作原理詳解SpringMVC
- SpringMVC詳解(補加)SpringMVC
- 軟體架構-nginx詳解上架構Nginx
- 1.5 比特幣架構詳解比特幣架構
- [大資料] Spark架構詳解大資料Spark架構
- 乾貨:軟體架構詳解架構
- Android 檢視架構詳解Android架構
- Android架構元件WorkManager詳解Android架構元件
- MySQL 主從架構配置詳解MySql架構
- 構建微服務分散式雲架構詳細步驟微服務分散式架構
- SpringMVC--常用註解(詳解)SpringMVC
- 最全最強SpringMVC詳細示例實戰SpringMVC
- Serverless無伺服器架構詳解Server伺服器架構
- 一文詳解微服務架構微服務架構
- tomcat架構分析及配置詳解Tomcat架構
- 【DATAGUARD】Oracle Dataguard體系架構詳解Oracle架構
- CynosDB技術詳解——架構設計架構
- ClickHouse、Doris、 Impala等MPP架構詳解架構