天天看點

SpringMVC詳解(二)------詳細架構

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 處理請求流程

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" 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

<!-- 配置處理器擴充卡,所有擴充卡都得實作 HandlerAdapter接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> 
      

  我們可以檢視源碼: 

SpringMVC詳解(二)------詳細架構

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

<!-- 配置處理器擴充卡第二種方法,所有擴充卡都得實作 HandlerAdapter接口 ,這樣配置所有Handler都得實作 HttpRequestHandler接口-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" /> 
      
SpringMVC詳解(二)------詳細架構

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 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、配置視圖解析器

  第一種配置:

<!-- 配置視圖解析器 
  	進行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詳解(二)------詳細架構

  在 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

作者:IT可樂

出處:http://www.cnblogs.com/ysocean/

資源:微信搜【IT可樂】關注我,回複 【電子書】有我特别篩選的免費電子書。

本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。