基本概念
三層架構
我們的開發架構一般都是基於兩種形式,一種是 C/S 架構,也就是客戶端/服務器,另一種是 B/S 架構,也就是瀏覽器服務器。在 JavaEE 開發中,幾乎全都是基於 B/S 架構的開發。那么在 B/S 架構中,系統標准的三層架構包括:表現層、業務層、持久層。下面介紹一下每層負責的功能。
表現層
web層,負責接收客戶端(比如瀏覽器)的請求,向客戶端響應結果。通常客戶端使用 http協議請求web 層, web 需要接收 http 請求,完成 http 響應。
表現層又分為控制層和展示層。
控制層:負責接收請求
展示層:負責結果的展示
表現層依賴業務層,接收到客戶端請求一般會調用業務層進行業務處理,並將處理結果響應給客戶端。表現層的設計一般都使用 MVC 模型。( MVC 是表現層的設計模型,和其他層沒有關系)
業務層
service層,負責業務邏輯處理,實現開發需求。web層依賴業務層,但業務層不依賴web層。
如果要對數據持久化需要保證事務一致性,在業務處理時,依賴持久層。
持久層
dao層。負責數據持久化,包括數據層(數據庫)和數據訪問層。持久層就是和數據庫交互,對數據庫表進行曾刪改查的。
數據庫:對數據進行持久化的載體
數據訪問層:業務層和持久層交互的接口。
MVC模型
全名Model View Controller,是一種用於設計創建 Web 應用程序表現層的模式。
Model:模型。通常指的就是我們的數據模型。一般用於封裝數據。
View:視圖。通常指的就是我們的 jsp 或者 html。一般用於展示數據。通常視圖是依據模型數據創建。
Controller:控制器。是應用程序中處理用戶交互的部分。 一般用於處理程序邏輯。
SpringMVC入門案例
概述
SpringMVC是什么
- 是一種基於Java實現的MVC設計模型的請求驅動類型的輕量級WEB框架。
- 屬於 SpringFrameWork 的后續產品,已經融合在 Spring Web Flow 里面。 Spring 框架提供了構建 Web 應用程序的全功能 MVC 模塊。
- 使用 Spring 可插入的 MVC 架構,從而在使用 Spring 進行 WEB 開發時,可以選擇使用 Spring的 Spring MVC 框架或集成其他 MVC 開發框架,如 Struts1(現在一般不用), Struts2 等。
優勢
-
清晰的角色划分:
前端控制器( DispatcherServlet)
請求到處理器映射( HandlerMapping)
處理器適配器( HandlerAdapter)
視圖解析器( ViewResolver)
處理器或頁面控制器( Controller)
驗證器( Validator)
命令對象( Command 請求參數綁定到的對象就叫命令對象)
表單對象( Form Object 提供給表單展示和提交到的對象就叫表單對象)。 -
分工明確,而且擴展點相當靈活,可以很容易擴展,雖然幾乎不需要。
-
由於命令對象就是一個 POJO,無需繼承框架特定 API,可以使用命令對象直接作為業務對象。
-
和 Spring 其他框架無縫集成,是其它 Web 框架所不具備的。
-
可適配,通過 HandlerAdapter 可以支持任意的類作為處理器。
-
可定制性, HandlerMapping、 ViewResolver 等能夠非常簡單的定制。
-
功能強大的數據驗證、格式化、綁定機制。
-
利用 Spring 提供的 Mock 對象能夠非常簡單的進行 Web 層單元測試。
-
本地化、主題的解析的支持,使我們更容易進行國際化和主題的切換。
-
強大的 JSP 標簽庫,使 JSP 編寫更容易。
-
還有比如RESTful風格的支持、簡單的文件上傳、約定大於配置的契約式編程支持、基於注解的零配
置支持等等。
與Structs2區別
共同點:
都是基於MVC模型編寫的表現層框架
底層都離不開原始ServletAPI
處理請求的機制都是一個核心控制器
區別:
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
Spring MVC 是基於方法設計的,而 Struts2 是基於類, Struts2 每次執行都會創建一個動作類。所
以 Spring MVC 會稍微比 Struts2 快些。Spring MVC 使用更加簡潔,同時還支持 JSR303, 處理 ajax 的請求更方便 。(JSR303 是一套 JavaBean 參數校驗的標准,它定義了很多常用的校驗注解,我們可以直接將這些注解加在我們 JavaBean 的屬性上面,就可以在需要校驗的時候進行校驗了。 )
Struts2 的 OGNL 表達式使頁面的開發效率相比 Spring MVC 更高些,但執行效率並沒有比 JSTL 提升,尤其是 struts2 的表單標簽,遠沒有 html 執行效率高。
SpringMVC入門程序
-
使用骨架新建一個maven工程
-
新建java,resources文件夾,並將其分別設置為
Sources Root
和Resources Root
,設置成功后的目錄。 -
引入相關的jar包
<!-- 版本鎖定 --> <properties> <spring.version>5.0.2.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</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>
-
在web.xml配置文件中配置核心的控制器(DispatcherServlet)
<!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> <!-- SpringMVC的核心控制器 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置Servlet的初始化參數,讀取springmvc的配置文件,創建spring容器 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!--配置servlet啟動時加載對象--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
在resources目錄下創建springmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置spring創建容器時要掃描的包 --> <context:component-scan base-package="com.ben"></context:component-scan> <!-- 配置視圖解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置spring開啟注解mvc的支持--> <mvc:annotation-driven></mvc:annotation-driven> </beans>
-
編寫index.jsp和Hellocontroller控制器類
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>入門程序</title> </head> <body> <h3>入門程序</h3> <a href="hello">點我啊</a> </body> </html>
HelloController.java
/** * @ClassName: HelloController * @author: benjamin * @version: 1.0 * @description: 控制器 */ @Controller public class HelloController { /* 接受請求 */ @RequestMapping("/hello") public String sayHello(){ System.out.println("Hello SpringMVC!"); return "success"; } }
-
在WEB-INF目錄下創建pages文件夾,編寫success.jsp的成功頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>入門成功</h3> </body> </html>
測試,點擊超鏈接轉入新頁面
入門案例執行過程分析
- 服務器啟動,應用被加載。 讀取到 web.xml 中的配置,創建 spring 容器並且初始化容器中的對象 ;
- SpringMVC的核心控制器 DispatcherServlet對象 被創建
- springmvc.xml配置文件被加載,創建spring容器,
- 開啟注解掃描,HelloController對象創建成功
- 視圖解析器InternalResourceViewResolver對象創建成功,以后有人調用這個類,就會解析到對應的jsp文件;
- 開啟SpringMVC的注解支持,誰發請求就能找到對應對象中的方法
- 瀏覽器發送請求,被DispatcherServlet捕獲,該Severlet並不處理請求,而是將請求轉發出去,轉發的路徑是根據請求的URL,匹配@RequestMapping中的內容;
- 匹配到了后,執行對應方法。該方法有一個返回值。;
- 根據方法的返回值,視圖解析器InternalResourceViewResolver找到對應的結果視圖;
- 渲染結果視圖,響應瀏覽器。
入門程序中涉及的組件
-
前端控制器(DispatcherServlet)
用戶請求到達前端控制器,它就相當於 mvc 模式中的 c, dispatcherServlet 是整個流程控制的中心,由它調用其它組件處理用戶的請求, dispatcherServlet 的存在降低了組件之間的耦合性。
-
處理器映射器(HandlerMapping)
HandlerMapping 負責根據用戶請求找到 Handler 即處理器, SpringMVC 提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,注解方式等。
-
處理器(Handler)
開發中要編寫的具體業務控制器。由 DispatcherServlet 把用戶請求轉發到 Handler。由Handler 對具體的用戶請求進行處理
-
處理器適配器(HandlAdapter)
通過 HandlerAdapter 對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更多類型的處理器進行執行。
-
視圖解析器(View Resolver)
View Resolver 負責將處理結果生成 View 視圖, View Resolver 首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成 View 視圖對象,最后對 View 進行渲染將處理結果通過頁面展示給用戶。
-
視圖(View)
SpringMVC 框架提供了很多的 View 視圖類型的支持,包括: jstlView、freemarkerView、 pdfView等。我們最常用的視圖就是 jsp。一般情況下需要通過頁面標簽或頁面模版技術將模型數據通過頁面展示給用戶,需要由程序員根據業務需求開
發具體的頁面。 -
<mvc:annotation-driven>
說明在 SpringMVC 的各個組件中,處理器映射器、處理器適配器、視圖解析器稱為 SpringMVC 的三大組件。
使 用
<mvc:annotation-driven>
自 動 加 載RequestMappingHandlerMapping
( 處 理 映 射 器 ) 和RequestMappingHandlerAdapter
( 處 理 適 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用<mvc:annotation-driven>
替代注解處理器和適配器的配置。
RequestMapping注解
源碼:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {}
作用:用於建立請求 URL 和處理請求方法之間的對應關系。
出現位置:
-
類上
請求 URL 的第一級訪問目錄。此處不寫的話,就相當於應用的根目錄。 寫的話需要以/開頭。它出現的目的是為了使我們的 URL 可以按照模塊化管理:
比如:
賬戶模塊:中第一級訪問目錄/account
/account/add
/account/update
/account/delete -
方法上
請求 URL 的第二級訪問目錄。
屬性:
value:用於指定請求的 URL ,如果注解里只有一個屬性,value關鍵字可以省略
path:和value屬性作用一樣。
method:用於指定請求的方式。RequestMethod.XXX
@RequestMapping(value = "/test",method = {RequestMethod.POST})
public String testRequestMapping(){
System.out.println("測試RequestMapping中的屬性");
return "success";
}
輸出:案例中指定POST請求才會有結果,因此會出現405錯誤;
params:用於指定限制請求參數的條件。 它支持簡單的表達式。 要求請求參數的 key 和 value 必須和配置的一模一樣。
jsp頁面:
<body>
<h3>入門程序</h3>
<a href="test2?username=hehe">RequestMapping注解</a>
</body>
方法:
//測試RequestMapping中的屬性
@RequestMapping(value = "/test2",params = {"username=hehe"})
public String testRequestMapping(){
System.out.println("測試RequestMapping中的屬性");
return "success";
}