- 人人都玩開(kāi)心網(wǎng):Ext JS+Android+SSH整合開(kāi)發(fā)Web與移動(dòng)SNS
- 李寧編著
- 2727字
- 2018-12-27 18:57:24
2.1 MVC框架的王者:Struts 2
Struts 2是當(dāng)今最吸引眼球,也是使用最廣泛的基于Java的MVC框架。該框架比其前身Struts 1.x更強(qiáng)大,也更容易使用。雖然Struts 2是Struts 1.x的升級(jí)版,但在技術(shù)實(shí)現(xiàn)上幾乎和Struts 1.x一點(diǎn)關(guān)系都沒(méi)有。實(shí)際上,Struts 2是從Webwork發(fā)展而來(lái)的。Struts 2借用了Struts的知名度和Webwork的優(yōu)良的設(shè)計(jì)和理念,成為新的MVC框架的王者。
2.1.1 Struts 2與MVC模式
MVC這個(gè)詞也許很多讀者并不陌生,可能耳朵都聽(tīng)得磨出繭子來(lái)了。MVC實(shí)際上是三個(gè)英文單詞的首字母的組合。M表示Model(模型), V表示View(視圖), C表示Controller (控制器)。基于MVC模式的應(yīng)用程序從邏輯上被分為Model-View-Controller三部分。也可以換句話說(shuō),所有從邏輯上可以分成Model-View-Controller三部分的應(yīng)用程序都是基于MVC模式的(包括B/S和C/S結(jié)構(gòu)的應(yīng)用程序)。
那么MVC的這三個(gè)部分到底有什么作用呢?讓我們先來(lái)回顧一下傳統(tǒng)的Java Web程序是如何設(shè)計(jì)的。在MVC模式受到廣泛關(guān)注之前,我們可能會(huì)這樣設(shè)計(jì)Web應(yīng)用程序。
在工程中建立很多的JSP頁(yè)面和Servlet類。Web程序的用戶接口主要是JSP頁(yè)面,那么網(wǎng)頁(yè)設(shè)計(jì)人員就用各種工具設(shè)計(jì)了很漂亮的JSP頁(yè)面(有可能是HTML頁(yè)面,然后由開(kāi)發(fā)人員將這些頁(yè)面轉(zhuǎn)成JSP頁(yè)面)。下一步,也是最核心的一步,就是為系統(tǒng)添加業(yè)務(wù)邏輯。開(kāi)發(fā)人員可能會(huì)在JSP中添加大量的JSTL標(biāo)簽以及Java代碼來(lái)處理需要?jiǎng)討B(tài)生成的頁(yè)面元素。當(dāng)JSP頁(yè)面需要提交請(qǐng)求時(shí),會(huì)提交給另一個(gè)JSP頁(yè)面,也可能會(huì)提交給Servlet。然后在這些JSP頁(yè)面或Servlet中處理相應(yīng)的業(yè)務(wù)邏輯(包括訪問(wèn)數(shù)據(jù)庫(kù)等操作),最后返回給JSP頁(yè)面,并以用戶期望的格式顯示處理結(jié)果。
從上面的處理過(guò)程來(lái)看,并沒(méi)有什么不妥。但如果要發(fā)生下面的情況應(yīng)該怎么辦呢?
當(dāng)JSP頁(yè)面的顯示風(fēng)格有變化時(shí),可能會(huì)修改原來(lái)的代碼。例如,在JSP頁(yè)面中原來(lái)是以列表的方式顯示處理結(jié)果的,但現(xiàn)在要以樹形結(jié)構(gòu)顯示處理結(jié)果。在這種情況下,修改JSP頁(yè)面是必然的,但服務(wù)端程序(JSP頁(yè)面或Servlet)返回的數(shù)據(jù)格式有可能并不符合JSP頁(yè)面的要求,或者需要對(duì)返回的數(shù)據(jù)進(jìn)一步加工才能滿足需求。這時(shí)如果按傳統(tǒng)的系統(tǒng)結(jié)構(gòu),就需要修改原來(lái)的JSP頁(yè)面或Servlet中的代碼。從技術(shù)上看,這么做沒(méi)有任何問(wèn)題。但這也違背了設(shè)計(jì)模式的一個(gè)重要原則:對(duì)修改關(guān)閉,對(duì)擴(kuò)展開(kāi)放。也就是在添加或修改系統(tǒng)的功能時(shí),應(yīng)盡量采用擴(kuò)展的方式,而不是修改原來(lái)的代碼。這樣做可以大大避免由于修改原來(lái)的代碼而引發(fā)的連鎖反應(yīng)。
那么如果不修改服務(wù)端程序的代碼,應(yīng)該如何做呢?聰明的程序員也許會(huì)想到另外一招。就是在服務(wù)端再添加一個(gè)Servlet(當(dāng)然也可以使用JSP頁(yè)面,不過(guò)處理客戶端請(qǐng)求最好用Servlet),這個(gè)Servlet作為JSP頁(yè)面和處理業(yè)務(wù)邏輯的Servlet的橋梁。也就是說(shuō),JSP頁(yè)面并不直接將信息提交給處理業(yè)務(wù)邏輯的Servlet,而是提交給剛才新添加的Servlet。而由這個(gè)新添加的Servlet再訪問(wèn)處理業(yè)務(wù)邏輯的Servlet。當(dāng)需要對(duì)返回?cái)?shù)據(jù)進(jìn)行二次加工時(shí),并不需要修改那個(gè)處理業(yè)務(wù)邏輯的Servlet,而只需要修改那個(gè)中間的Servlet的代碼即可。由于這個(gè)Servlet并不處理任何業(yè)務(wù)邏輯,而只是對(duì)返回的數(shù)據(jù)進(jìn)行加工,因此,可以完全重寫這個(gè)Servlet。
對(duì)于JSP頁(yè)面來(lái)說(shuō),可以只向這個(gè)中間的Servlet提交信息。當(dāng)服務(wù)端需要改變處理業(yè)務(wù)邏輯的模塊時(shí),只需要修改這個(gè)中間的Servlet即可。而這一步對(duì)JSP頁(yè)面是完全透明的。從這一點(diǎn)可以看出,這個(gè)中間的Servlet起到了一個(gè)控制的作用。對(duì)于客戶端來(lái)說(shuō),可以控制服務(wù)端返回的數(shù)據(jù)。對(duì)于服務(wù)端來(lái)說(shuō),可以決定將客戶端提交過(guò)來(lái)的請(qǐng)求交給哪個(gè)服務(wù)端程序來(lái)處理。那么我們就可以將這個(gè)中間的Servlet看做是一個(gè)Controller(控制器)。這種模式也就是MVC模式。其中M可以看做處理業(yè)務(wù)邏輯的Servlet, V可以看做是采集用戶數(shù)據(jù)的JSP頁(yè)面,而C則可以看做是這個(gè)中間的Servlet。
在Struts 2中也采用了類似的方式,只是并不是用Servlet來(lái)實(shí)現(xiàn)的。在Struts 2中采用了過(guò)濾器的方式來(lái)截獲客戶端的請(qǐng)求,并根據(jù)請(qǐng)求來(lái)調(diào)用Struts 2中的控制器。Struts 2中的控制器也被稱為Action對(duì)象。Action對(duì)象可以是任何類的對(duì)象實(shí)例,包括POJO類。而Struts 2 MVC中的M也并不是Servlet,而是一個(gè)或多個(gè)處理業(yè)務(wù)邏輯的JavaBean的對(duì)象實(shí)例。讀者在2.1.3節(jié)將會(huì)看到MVC模式在Struts 2中的真實(shí)應(yīng)用。
2.1.2 Struts 2最新版的下載與安裝
在筆者寫本書時(shí),Struts 2的最新版本是Struts 2.1.6。讀者可以從下面的網(wǎng)址下載Struts 2的最新版本:
在下載完Struts 2的壓縮包后,將其解壓。在lib目錄中包含了當(dāng)前Struts 2發(fā)行版所帶的所有jar文件。但基本的Struts 2應(yīng)用程序只需要下面7個(gè)jar文件:
· struts2-core-2.1.6.jar
· xwork-2.1.2.jar
· struts2-convention-plugin-2.1.6.jar
· ognl-2.6.11.jar
· freemarker-2.3.13.jar
· commons-logging-1.0.4.jar
· commons-fileupload-1.2.1.jar
在找到上面7個(gè)jar文件后,將這些jar文件復(fù)制到WEB-INF\lib目錄中,并在WEB-INF\web.xml文件中添加如下的代碼:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAnd ExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping>
2.1.3 通過(guò)一個(gè)計(jì)算加減法的Web程序來(lái)體驗(yàn)MVC模式的好處
在這一節(jié)我們來(lái)做一個(gè)計(jì)算加減法的Struts 2應(yīng)用程序。其中加法和減法分別由兩個(gè)模型(Model)類完成。這兩個(gè)模型類由Action類來(lái)調(diào)用。當(dāng)JSP頁(yè)面采集了兩個(gè)操作數(shù)后,會(huì)將數(shù)據(jù)提交給Action,然后Action根據(jù)不同的需求調(diào)用加法或減法模型類來(lái)計(jì)算業(yè)務(wù)邏輯,并對(duì)處理結(jié)果進(jìn)行二次加工。
1 編寫計(jì)算加法的模型類。
Addition類負(fù)責(zé)計(jì)算兩個(gè)操作數(shù)的加法,代碼如下:
package net.blogjava.nokiaguy.models; public class Addition { public int add(int x, int y) { return x + y;
} }
2 編寫計(jì)算減法的模型類。
Subtraction類負(fù)責(zé)計(jì)算兩個(gè)操作數(shù)的減法,代碼如下:
package net.blogjava.nokiaguy.models; public class Subtraction { public int sub(int x, int y) { return x - y; } }
3 編寫CalcAction類。
CalcAction類是一個(gè)調(diào)用Addition和Subtraction類的Action類,代碼如下:
package net.blogjava.nokiaguy.actions; import net.blogjava.nokiaguy.models.Addition; import net.blogjava.nokiaguy.models.Subtraction; public class CalcAction { // 獲得客戶端提交的兩個(gè)操作數(shù)的值 private int operand1; private int operand2; // 向客戶端返回結(jié)果Action類加工過(guò)的處理結(jié)果 private String result; . // 此處省略了屬性的getter和setter方法 // 處理業(yè)務(wù)邏輯的方法 public String execute() { Addition addition = new Addition(); // 調(diào)用add方法執(zhí)行業(yè)務(wù)邏輯 int value = addition.add(operand1, operand2); // 加工處理結(jié)果 result = operand1 +"+" + operand2 + "=" + value; return "success"; } }
從CalcAction類的代碼可以看出,在execute方法中只調(diào)用了Addition類。如果需要調(diào)用Subtraction類,可以修改execute方法,或?qū)⒃摲椒某蒭xecute1,并另外寫一個(gè)execute方法來(lái)調(diào)用Subtraction。由于JSP頁(yè)面只向CalcAction類提交請(qǐng)求,而且只從result屬性中獲得處理結(jié)果。因此,服務(wù)端的業(yè)務(wù)邏輯切換對(duì)于客戶端(JSP頁(yè)面)是透明的。
4 配置struts.xml文件。
struts.xml文件是Struts 2中的核心文件。在src目錄中建立一個(gè)struts.xml文件,并輸入如下的內(nèi)容:
<? xml version="1.0" encoding="UTF-8" ? > <! DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="struts2" namespace="/" extends="struts-default"> <! -- 配置CalcAction類 --> <action name="calc" class="net.blogjava.nokiaguy.actions.CalcAction"> <result name="success">/WEB-INF/calc.jsp </result> </action> <! -- 使用通配符為所有在WEB-INF目錄中的JSP頁(yè)面指定一個(gè)對(duì)應(yīng)的Action --> <action name="*_jsp"> <result>/WEB-INF/{1}.jsp </result> </action> </package> </struts>
由于本例中所有的JSP頁(yè)面都放在了WEB-INF目錄中,而且該目錄中的資源不允許直接被客戶端訪問(wèn),因此,在這里需要使用通配符為每一個(gè)位于WEB-INF目錄中的JSP頁(yè)面指定一個(gè)對(duì)應(yīng)的Action。比如在WEB-INF目錄中有一個(gè)calc.jsp頁(yè)面,那么可以通過(guò)如下的URL來(lái)訪問(wèn)這個(gè)JSP頁(yè)面:
http://localhost:8080/sshregister/calc_jsp.action
5 編寫calc.jsp頁(yè)面。
calc.jsp頁(yè)面有兩個(gè)功能:采集兩個(gè)操作數(shù)和顯示處理結(jié)果。在WEB-INF目錄中建立一個(gè)calc.jsp頁(yè)面,并輸入如下的代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <! -- 引用Struts 2的標(biāo)簽庫(kù) --> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>計(jì)算器</title> </head> <body> <! -- 顯示處理結(jié)果 --> <s:property value="result"/> <! -- 顯示采集兩個(gè)操作數(shù)的表單,并向calc提交請(qǐng)求 --> <s:form action="calc"> <s:textfield label="操作數(shù)1" name="operand1" /> <s:textfield label="操作數(shù)2" name="operand2" /> <s:submit value="計(jì)算"/> </s:form>
</body> </html>
到現(xiàn)在為止,這個(gè)例子已經(jīng)編寫完成了,啟動(dòng)Tomcat后,在瀏覽器地址欄中輸入如下的URL:
http://localhost:8080/sshregister/calc_jsp.action在頁(yè)面中的兩個(gè)文本框中分別輸入43和56,單擊【計(jì)算】按鈕,將會(huì)顯示如圖2.1所示的頁(yè)面。

圖2.1 計(jì)算加法
如果將CalcAction類中的execute方法名改成execute1,并加入如下的execute方法:
public String execute() { Subtraction subtraction = new Subtraction(); // 調(diào)用sub方法執(zhí)行業(yè)務(wù)邏輯 int value = subtraction.sub(operand1, operand2); // 加工處理結(jié)果 result = operand1 +"-" + operand2 + "=" + value; return "success"; }
這時(shí)再單擊圖2.1所示頁(yè)面上的【計(jì)算】按鈕,則會(huì)顯示如圖2.2所示的頁(yè)面。

圖2.2 計(jì)算減法
從上面的測(cè)試過(guò)程可以看出,JSP頁(yè)面和模型類的代碼都未修改,而只修改的Action類(Controller)就可以改變JSP頁(yè)面的顯示結(jié)果,而且更改了服務(wù)端的業(yè)務(wù)邏輯。
- 版面設(shè)計(jì)與制作
- Bootstrap響應(yīng)式Web開(kāi)發(fā)
- 園區(qū)網(wǎng)互聯(lián)及網(wǎng)站建設(shè)
- 網(wǎng)頁(yè)制作與網(wǎng)站建設(shè)寶典
- 速學(xué)速通:快學(xué)Flash動(dòng)畫制作
- Photoshop電商網(wǎng)頁(yè)廣告設(shè)計(jì)實(shí)戰(zhàn)從入門到精通
- 動(dòng)態(tài)網(wǎng)頁(yè)設(shè)計(jì)與制作(HTML5+CSS3+JavaScript)(第3版)
- HTML+CSS+JavaScript網(wǎng)頁(yè)制作(第2版)
- 中文版Dreamweaver CS6完全自學(xué)教程
- Linux系統(tǒng)與網(wǎng)絡(luò)服務(wù)管理技術(shù)大全(第二版)
- Web綜合實(shí)戰(zhàn)教程
- Dreamweaver CS6網(wǎng)頁(yè)設(shè)計(jì)入門、進(jìn)階與提高
- H5頁(yè)面設(shè)計(jì)與制作(全彩慕課版)
- 精通網(wǎng)站建設(shè):100%全能建站密碼
- HTML網(wǎng)頁(yè)設(shè)計(jì)案例指導(dǎo)