1.基本概念
1.1三層架構
三層架構也就是我們常說的b/s架構中的表現層,業務層和持久層,每層都各司其職,下面來分別講解這三層的作用。
表現層:
也就是我們常說的web層。它負責接收客戶端的請求,向客戶端響應結果,通常客戶端向web層發送HTTP請求,web層需要接收HTTP請求。表現層包含展示層和控制層,控制層負責接收前端請求,展示層負責結果的展示。表現層依賴業務層,接收到客戶端請求一般會調用業務層進行業務處理,并將處理結果響應給客戶端。表現層的設計一般都使用MVC模型。
業務層:
也就是我們常說的service層。它負責業務邏輯的處理,和我們開發項目的需求息息相關。web層依賴業務層,但是業務層不依賴web層。業務層在業務處理是可能會依賴持久層。
持久層:
也就是我們常說的dao層。負責數據持久化,包括數據層即數據庫和數據訪問層。數據庫是對數據進行持久化的載體,數據訪問層是業務層和持久層的接口,業務層需要通過對數據訪問層將數據持久化到數據庫中,通俗的講,持久化就是和數據庫交互,對數據庫進行增刪改查的。
1.2MVC架構
MVC全名是Model View Controller.是模型(Model) 視圖(view) 控制器 (controller)的縮寫。
是一種用于創建web應用程序表現層的模式。
MVC中每個部分各司 其職:
Model(模型):
通常指的就是我們的數據模型,用來封裝數據的。
View(視圖):
通常指的是我們的jsp或者html。一般用來展示數據的,通常視圖是依據模型數據創建的。
Controller(控制器):
是應用程序中處理用戶交互的部分。用于接收前端請求。比如獲取前端請求傳遞的參數并負責將請求交給業務層進行處理。業務層將業務結果處理完成以后,控制器接收業務 層的業務結果,并將業務數據存儲在域對象,實現頁面的跳轉。
1.3什么是SpringMVC
SpringMVC是一種基于Java的實現MVC設計模型的請求驅動類型的輕量級web框架, 屬于Spring FrameWork的后續產品,已經融合在Spring Web Flow里面。Spring框 架提供了構建web應用程序的全功能MVC模塊。使用Spring可插入的MVC架構,從而在使用 Spring進行web開發時,可以選擇使用Spring的Spring MVC框架或集成其他MVC開發框 架,比如Struts2等。
他其實就是基于servelet進行封裝的一個框架。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
SpringMVC已經成為目前最主流的MVC框架之一,并且隨著Spring 3.0的發布,全 面超越Struts2,成為最優秀的web框架。它通過一套注解,讓一個簡單的Java類成為處理 請求的控制器,而無需事先任何接口,同時它還支持Restful編程風格
1.4SpringMVC的優勢
1. 清晰的角色劃分: 前端控制器(DispatcherServlet) 處理器映射器(HandlerMapping) 處理器適配器(HandlerAdpater) 視圖解析器(ViewResolver) 控制器(Controller) 驗證器(Validator) 命令對象(Command 請求參數綁定到的對象就叫做命令對象) 表單對象(Form Object 提供給表單展示和提交的對象就叫表單對象)
2. 分工明確,而且擴展點相當靈活,很容易進行功能擴展。
3. 由于命令對象就是一個POJO,無需繼承框架特定的API,可以使用命令對象直接作為業 務對象。 4. 和Spring其他框架無縫集成,是其他web框架不具備的。
5. 可適配,通過HandlerAdapter可以支持任意的類作為處理器。
6. 可定制性,HandlerMapping ViewResolver等能夠非常簡單的定制。
7. 功能強大的數據驗證、格式化、綁定機制。
8. 利用Spring提供的Mock對象能夠非常簡單的進行web層單元測試。
9. 本地化、主題的解析支持,使我們更容易進行國際化和主題的切換。
10. 強大的JSP標簽庫,使JSP編寫更容易。 還有比如RESTFUL風格的支持,簡單的文件上傳、約定大于配置的契約式編程風格,基于注 解的零配置支持等。?
2.SpringMVC入門環境的搭建
首先使用maven創建一個web項目(基于骨架創建)
然后pom.xml文件中導入相關依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.xq</groupId><artifactId>xq-springmvc-project</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>springmvc-project-quickstart</artifactId><packaging>war</packaging><name>springmvc-project-quickstart Maven Webapp</name><url>http://maven.apache.org</url>
<properties>
<spring.verion>5.0.2.RELEASE</spring.verion>
</properties>
<dependencies>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.verion}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.verion}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.verion}</version>
</dependency>
<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope>
</dependency>
<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope>
</dependency>
</dependencies><!--配置tomcat7插件-->
<build><finalName>springmvc-project-quickstart</finalName>
<plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><path>/</path><port>8088</port><uriEncoding>UTF-8</uriEncoding></configuration></plugin>
</plugins>
</build>
</project>
至于用什么版本倒是無所謂,可以選更高的。
接著在web.xml中配置前端控制器
?
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><servlet><servlet-name>SpringMVCDispatcherServlet</servlet-name><servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class><!-- 配置初始化參數,用于讀取 SpringMVC 的配置文件 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置 servlet 的對象的創建時間點:應用加載時創建。
取值只能是非 0 正整數,表示啟動順序 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>SpringMVCDispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>?
<servlet-name>:為 Servlet 定義一個唯一的名稱,這里是 SpringMVCDispatcherServlet,后續在 <servlet-mapping> 中會使用這個名稱來映射 URL。
<servlet-class>:指定 Servlet 的全限定類名,這里使用的是 Spring MVC 的核心 Servlet org.springframework.web.servlet.DispatcherServlet。DispatcherServlet 是 Spring MVC 的前端控制器,負責接收所有的 HTTP 請求,并將請求分發給相應的處理器進行處理。
<init-param>:用于配置 Servlet 的初始化參數。
<param-name>:參數名稱,這里是 contextConfigLocation,表示要指定 Spring MVC 的配置文件位置。
<param-value>:參數值,classpath:springmvc.xml 表示從類路徑下加載 springmvc.xml 文件作為 Spring MVC 的配置文件。
<load-on-startup>:指定 Servlet 的加載順序。取值為非 0 正整數,數值越小,Servlet 會越早被加載。這里設置為 1,表示在 Web 應用啟動時就創建并初始化這個 Servlet。?
<servlet-name>:指定要映射的 Servlet 的名稱,這里要與前面 <servlet> 元素中定義的 servlet-name 一致,即 SpringMVCDispatcherServlet。
<url-pattern>:指定 Servlet 要處理的 URL 模式。/ 表示將所有的 HTTP 請求都映射到 SpringMVCDispatcherServlet 進行處理。
然后編寫springmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?><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 容器要掃描的包 --><context:component-scan base-package="com.xq"></context:component-scan><!-- 配置視圖解析器 --><bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/pages/"></property><property name="suffix" value=".jsp"></property></bean><!--開啟springmvc注解支持--><mvc:annotation-driven></mvc:annotation-driven></beans>
接著在webapp的pages(自己創建)目錄下,編寫success.jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><h2>歡迎你。這是一個成功頁面</h2></body></html>
最后編寫控制器代碼
@Controllerpublic class HelloController {@RequestMapping("/hello")public String sayHello(){System.out.println("hello,springmvc");return "success";}}
編寫控制器代碼,用于接收前端發送的請求,并進行頁面的跳轉。
整體項目結構如下
2.1入門程序分析
首先來看SpringMVC的執行流程
具體執行步驟如下
第一步:發起請求到前端控制器(DispatcherServlet)
第二步:前端控制器請求HandlerMapping查找 Handler (可以根據xml配 置、注解進行查找)
第三步:處理器映射器HandlerMapping向前端控制器返回Handler, HandlerMapping會把請求映射為HandlerExecutionChain對象(包含一個 Handler處理器(頁面控制器)對象,多個HandlerInterceptor攔截器對 象),通過這種策略模式,很容易添加新的映射策略
第四步:前端控制器調用處理器適配器去執行Handler
第五步:處理器適配器HandlerAdapter將會根據適配的結果去執行 Handler
第六步:Handler執行完成給適配器返回ModelAndView
第七步:處理器適配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一個底層對象,包括 Model和 view)
第八步:前端控制器請求視圖解析器去進行視圖解析 (根據邏輯視圖名解 析成真正的視圖(jsp)),通過這種策略很容易更換其他視圖技術,只需要更 改視圖解析器即可
第九步:視圖解析器向前端控制器返回View
第十步:前端控制器進行視圖渲染 (視圖渲染將模型數據(在 ModelAndView對象中)填充到request域)
第十一步:前端控制器向用戶響應結果?
2.2SpringMVC核心組件
DispatcherServlet 前端控制器
用戶請求到達前端控制器,它就相當于mvc模式中的c,dispatcherServlet 是整個流程控制的中心,由它調用其它組件處理用戶的請求, dispatcherServlet 的存在降低了組件之間的耦合性。
HandlerMapping 處理器映射器
HandlerMapping負責根據用戶請求找到 Handler 即處理器,SpringMVC 提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口 方式,注解方式等。
Handler 處理器
它就是我們開發中要編寫的具體業務控制器。由DispatcherServlet 把用戶 請求轉發到 Handler。由Handler對具體的用戶請求進行處理。
HandlAdapter 處理器適配器
通過 HandlerAdapter 對處理器進行執行,這是適配器模式的應用,通過擴 展適配器可以對更多類型的處理器進行執行。
ViewResolver 視圖解析器
View Resolver負責將處理結果生成View 視圖,View Resolver首先根據邏 輯視圖名解析成物理視圖名即具體的頁面地址,再生成 View視圖對象,最 后對View進行渲染將處理結果通過頁面展示給用戶。
View 視圖
SpringMVC框架提供了很多View視圖類型的支持,包括:jstlView、 freemarkerView、pdfView等。我們最常用的視圖就是jsp。一般情況下需 要通過頁面標簽或頁面模版技術將模型數據通過頁面展示給用戶,需要由程 序員根據業務需求開發具體的頁面。
2.3RequestMapping注解的使用
作用:用于建立請求URL和處理請求方法之間的對應關系
它可以作用在類上(用于請求URL的第一級訪問目錄),也可以作用在方法上(用于請求URL的第二級訪問目錄).
相關屬性:
value:描述的是請求資源的URL路徑.它和path屬性的作用是一樣的.
method:用于指定請求的方法,例如GET,POST方法
params:用于指定限制請求參數的條件
如果括號里只有一個屬性,如果不指定具體的屬性,那么默認就是value.
使用示例
@Controller
@RequestMapping("demo1")
public class HelloController{
@requestMapping("/hello")
public String sayHello(){
System.out.println("hello")
return "success";}
}
那么此時我們的訪問路徑應該是localhost:8088/demo1/hello
這里的'/'可要可不要
不知道有人會不會有點疑惑,為什么注解既可以放在方法上,又可以放在類上,為什么都不直接放在方法上,就不用放在類上了.
就像這里,三個模塊都用一樣的注解,這樣在進行資源定位時就不知道到底是哪個模塊的,所以要在每個類上面再分別加上注解來區分?
變成這樣就行了?
再具體講一下params
當它只指定了參數名時,只需要再路徑名中加上該參數并給它賦值即可成功訪問該方法,例如
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class ParamController {@RequestMapping(value = "/test", params = "param1")@ResponseBodypublic String handleRequest() {return "Request contains param1";}
}
這里的訪問路徑就需要再在請求text?路徑時包含?param1
?參數,handleRequest
?方法才會被調用。例如,/test?param1=value
?會匹配該方法,但?/test
?不會匹配。
它也可以給該參數限定范圍,例如params="params=a",那么在請求時必須在寫成/text?paraml=a才行
他也可以限定成params!="a",就是表示只要不等于a的值填上去就行
2.4請求參數綁定
我們都知道,用戶請求參數都是基于key=value的。SpringMVC綁定請求參數的過程是通過把請求提交的參數,作為控制器中的方法參數進行綁定.
Springmvc支持的參數綁定類型:
基本類型參數: 包括基本類型和String類型
POJO類型參數:包括實體類及其關聯的實體類
數組和集合類型的參數:包括List和Map結構的集合(包括數組)
SpringMVC綁定請求參數是自動實現的,但是使用必須遵循器使用要求:
如果是基本類型或者String類型: 要求我們的參數名稱必須和控制器方法中 的形參名稱保持一致,并嚴格區分大小寫。
如果是POJO類型,或者其他關聯對象:要求表單中的參數名稱和POJO類的 屬性名稱一模一樣,并且控制器方法的參數類型是POJO類型。
下面以基本參數類型為例
先編寫一個超鏈接
<a href="${pageContext.request.contextPath}/demo1/getBasicParam?username=eric">[提交基本數據類型的參數]</a>
然后編寫控制器方法
@Controller@RequestMapping("demo1")public class HelloController {@RequestMapping("getBasicParam")public String getBasicParam(String username){System.out.println("username: " + username);return "success";}
}
控制器會捕捉前端傳過來的參數,用的是控制器下的方法來捕捉,這里的方法就是捕捉了String類型的參數。這里不僅要保持參數的類型保持一致,還要保持參數的名稱保持一致才能被自動綁定,不然就要采取其他方法來實現。