Struts 培訓教程
1 概述
在這份教程中,將介紹struts框架和與struts框架有關的技術。該教程主要分為以下幾部分:
§ MVC模式
§ Struts的概念和體系結構
§ Struts中主要技術的介紹
§ 用jBuilder8開發struts應用程序
2 MVC模式
所謂的MVC模式,即 模型—視圖—控制器(model—view--controller)模式。其結構圖如下:
View Model Controller
§ Model端
在MVC中,模型是執行某些任務的代碼,而這部分代碼并沒有任何邏輯決定它對用戶端的表示方法。Model只有純粹的功能性接口,也就是一系列的公開方法,通過這些公開方法,便可以取得模型端的所有功能。在struts框架中,Model端是用Action和EJB技術實現的。
§ View端
在MVC模式里,一個Model可以有幾個View端,而實際上復數的View端是使用MVC的原始動機。使用MVC模式可以允許多于一個的View端存在,并可以在需要的時候動態的登記上所需要的View.
§ Controller端
MVC模式的視圖端是與MVC的控制器結合使用的。當用戶端與相應的視圖發生交互時,用戶可以通過視窗更新模型的狀態,而這種更新是通過控制器端進行的。控制器端通過調用模型端的方法更改其狀態值。與此同時,控制器端會通知所有的登記了的視圖刷新顯示給用戶的表示。
在現在的j2ee應用中,我們在開發web server時基本上都是采用MVC模式來開發的,j2ee規范也相應的為我們提供了技術支持,請看下圖:
Web Server 2 6 5
Browser Action Servlet EJB Server
1 2
JSP
1 瀏覽器用戶執行servlet的doGet方法;
2 servlet根據不同的請求,將他們分發到不同的Action中。在這里,servlet的作用就好比是controller;
3 Action調用EJB層的商務邏輯程序處理用戶的請求;
4 EJB層返回給Action處理結果;
5 Action 對將處理結果返回給servlet。在這里,可以將Action 和 EJB共同看成是model
6 servlet將信息發送給JSP頁面。這里的JSP就相當于view;
7 browser用戶瀏覽JSP頁面;
大家可以看到,JSP、servlet和EJB各自在MVC模式中所起到的作用。
使用MVC的優點如下:
§ 可靠性(Reliability):將表示層和處理層完全分開,可以在不重新編譯model和controller的情況下修改view層。
§ 復用性和適應性(reuse & adaptability):MVC使你可以使用多種view去訪問相同的model。
§ 快速開發(Rapid deployment):因為MVC清晰的將表示層和處理層分開,所以使得不同的程序員可以各司其則,增加開發速度。
§ 可維護性(Maintainability):清晰的分層同樣使得代碼清晰、程序的可維護性提高。
3 Struts的概念和體系結構
§ 概述
struts源自于apache的jakarta工程,是一個開源代碼工程(http://jakarta.apache.org/)。現在struts最新的版本是1.2,而jBuilder自帶的版本是1.02。struts是一個完全遵照MVC模型設計的,web層的框架。
§ struts與MVC模式
struts是一個完全遵照MVC模型設計的,web層的框架。在struts中,使用到了jsp、javabean、taglib和servlet技術。下圖是一個描述了struts框架的應用請求的執行路徑:
這個過程大體可以被分成5個基本步驟:
1 view發起一個請求
2 ActionServlet(servlet技術實現)接受這個請求,它根據一份xml文件來得到處理這個請求的Action對象,并將請求發送給這個Action對象。
3 Action對象接受這個請求,并調用model(EJB)去處理這個請求,并將處理結果返回給ActionServlet。
4 ActionServlet根據Action 的返回結果中的信息,決定將處理結果返回給對應的view。
5 view得到處理結果,并將他顯示給用戶。
3.1 THE MODEL
Struts框架提供Action作為model的一種實現。Action 是繼承org.apache.struts.action. Action的類,他用來處理用戶的請求,并將處理結果封裝在HttpServletRequest中,返回給ActionServlet。
3.2 THE VIEW
Struts用JSP、taglib和javabean技術去實現view。JSP用來顯示視圖;struts通過使用自己定義的一組taglib來控制請求的流程、輔助處理結果的顯示;javabean用來保存用戶在JSP頁面中的輸入數據,他用來方便的向Action傳遞用戶輸入數據。
3.3 THE CONTROLLER
Struts用org.apache.struts.action.ActionServlet去實現controller的功能。這個servlet接收所有JSP頁面發送的請求,根據一份配置文件得到處理相應用戶請求的Action,并調用Action去處理用戶的請求。當Action處理結束后,ActionServlet接受處理結果,并根據同樣的配置文件將處理結果發送當相應的JSP頁面。
4 Struts主要技術介紹
4.1 相關技術
學習Struts,首先要了解一下以下相關技術。(有些部分只提供相關的資料鏈接,不做講解)。
4.1.1 JavaBeans
大多數JavaBeans是由JavaBeans來編寫的.
· The JavaBeans Component Architecture Documentation page at
java.sun.com, including a link to download the JavaBeans 1.01 Specification
· The JavaBean Trail in the Java Tutorial
· JavaBeans Components in JSP Pages in the Java Web Services Tutorial
4.1.2 反射和內省
反射機制是一種決定一個對象哪些成員域和成員方法被采用的過程。內省技術是反射機制的一種特殊機制,Structs使用內省技術轉換HTTP參數為JavaBean的屬性,讀取JavaBean屬性裝配HTML字段。
· Chapter 8 of the JavaBeans API Specification
4.1.3 屬性文件和ResourceBundles
4.1.3.1 屬性文件
屬性文件主要用來設置程序屬性,屬性文件的后綴名為.properties,屬性文件的格式類似于以下內容:
book=my computer book
pages=120
authors=zhf
seminar=12
4.1.3.2 使用屬性文件
java.util包中Properties類用來管理一個Key/value對,Properties類提供了以下方法:
load()方法:Loading key/value pairs into a Properties object form a Stream 從一個輸入流中加載
getProperty()方法:Retrieving a value from its key 通過關鍵字來獲得值
list()方法:Listing the keys and their values 列舉
Save()方法:Saving the properties to a stream 保存屬性
具體例子如下
import java.util.*;
import java.io.*;
public class useProperties
{
public static void main(String[] args)
{
try{
Properties defaultProps=new Properties();
FileInputStream file=new FileInputStream("test.properties");
defaultProps.load(file);
file.close();
defaultProps.list(System.out);
System.out.println("getProperty(String key,Stringdefault)= "
+defaultProps.getProperty("book"));
FileOutputStream out=new FileOutputStream("appProperties");
defaultProps.store(out,"-----no comment--");
out.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
}
4.1.3.3 使用本地化數據
使用本地化數據,需要建立多個屬性文件,假設我們系統中需要支持德文和法文,我們的默認屬性文件為LabelsBundle.properties文件,那么我們需要建立德文和法文所對應的屬性文件:
LabelBundle_de.properties
LabelBundle_fr.properties
# LabelsBundle.properties 內容
s1 = computer
s2 = disk
s3 = monitor
s4 = keyboard
# LabelsBundle_de.properties內容
s1 = Computer
s2 = Platte
s3 = Monitor
s4 = Tastatur
# LabelsBundle_fr.properties內容
s1 = Computerfr
s2 = Plattefr
s3 = Monitorfr
s4 = Tastaturfr
4.1.3.4 ResoureBundle和Locale
通過ResourceBundle結合Locale對象可以選擇屬性文件:
下面我們給一個具體的例子
import java.util.*;
import java.io.*;
public class ResourceBundleDemo{
public static void main(String[] args)
{
//采用了德國設置
Locale currentLocal=Locale.GERMAN;
ResourceBundle labels=ResourceBundle.getBundle("LabelsBundle",currentLocal);
String myValue=labels.getString("s2");
System.out.println(" Local=GERMAN ; S2= "+myValue);
//采用了法國設置
currentLocal=Locale.FRENCH;
labels=ResourceBundle.getBundle("LabelsBundle",currentLocal);
myValue=labels.getString("s2");
System.out.println(" Local= FRENCH ; S2= "+myValue);
}
}
更多的內容可以查看:
· Using Properties to Manage Program Attributes in The Java Tutorial
· About the ResourceBundle Class in the Java Tutorial
4.1.4 JSP和JSP標簽庫
Jsp中提供了一些標準的標簽:
useBean,setProperty/getProperty,include,forward,plugin。
使用例子如:
<jsp:useBean id=”bookname” scope=”page” class=”test.book”/>
這些標準的標簽,為操作JavaBean和相應請求等提供便利,除此之外,JSP技術允許我們自己封裝特有的標簽,來簡化應用程序開發。有經驗的開發者可以利用標簽處理表單,訪問數據庫或其他企業服務(如e-mail或目錄服務等)。
4.1.4.1 標簽的主要技術
可以在JSP頁面中設置標簽的參數。
可以訪問JSP頁面中所有的對象。
可以獲得JSP頁面的Response對象。
標簽之間互相通訊。
標簽可以被嵌套,實現標簽的多層使用。
4.1.4.2 標簽的使用
為了能夠在jsp頁面中使用一個標簽,我們需要變現一個實現了TagSupport類的java程序,然后通過tld文件,定義該標簽的屬性,然后通過web.xml聲明這個tld文件,最后才可以在JSP頁面中使用標簽的。
下面我還是根據例子來簡單講一下
詳細代碼下src/taguse目錄下。
4.1.4.2.1 定制標簽類
package com.zhfelva.tag;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
/**
* 一個顯示當前時間的標簽
*/
public class CurrentTimeTag extends TagSupport {
public int doStartTag() {
try {
JspWriter out = pageContext.getOut();
java.util.Date dt = new java.util.Date(System.currentTimeMillis());
out.print(dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds());
} catch(IOException ioe) {
System.out.println("Error in CurrentTimeTag: " + ioe);
}
return(SKIP_BODY);
}
}
4.1.4.2.2 編寫標簽定義文件
放于\WEB-INF\taglib\mytaglib.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/Web-jsptaglibrary_1_1.dtd">
<!-- a tag library descriptor -->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>current time</shortname>
<uri></uri>
<info>
A tag library for show current time
</info>
<tag>
<name>CurrentTime</name>
<tagclass>com.zhfelva.tag.CurrentTimeTag</tagclass>
<bodycontent>EMPTY</bodycontent>
<info>show current time</info>
</tag>
</taglib>
4.1.4.2.3 在web.xml中進行配置
一個網頁應用程序要在web.xml中聲明他要使用的標簽庫:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.3.dtd">
<web-app>
<taglib>
<taglib-uri>
my-taglib
</taglib-uri>
<taglib-location>
/WEB-INF/taglib/mytaglib.tld
</taglib-location>
</taglib>
</web-app>
4.1.4.2.4 簡單標簽的使用
以上配置做好之后,就可以在JSP頁面中使用標簽了:
currenttime.jsp
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="my-taglib" prefix="mytag" %>
<HTML>
<HEAD>
<TITLE>顯示當前時間 - JSP/TagLib</TITLE>
</HEAD>
<BODY>
<H1>顯示當前時間 - JSP/TagLib</H1>
<mytag:CurrentTime />
</BODY>
</HTML>
Struts中真正將標簽庫應用了起來,大家可以從中看到標簽庫的強大功能。
更多的內容可以查看:
- The JavaServer Pages Technology page at
java.sun.com
- The JSP 1.1 and 1.2 Specifications download page at
java.sun.com
- JavaServer Pages Technology in the Java Web Services Tutorial
- Custom Tags in JSP Pages in the Java Web Services Tutorial
4.1.5 XML相關技術
這里,相關的內容非常多,而且很重要,相信大家也都熟悉XML技術,由于時間關系,這里就不做講述了。
4.2 主要技術
4.2.1 Struts體系結構
Client IE or Netscape Controller ActionServlet Business Logic Action Model JavaBean or EJB View JSP HTTP Request Action Form HTTP Response Struts-config.xml Struts體系圖
控制:通過Struts體系圖大家可以看到有一個XML文件Struts-config.xml,與之相關聯的是Controller,在Struts中,承擔MVC中Controller角色的是一個Servlet,叫ActionServlet。ActionServlet是一個通用的控制組件。這個控制組件提供了處理所有發送到Struts的HTTP請求的入口點。它截取和分發這些請求到相應的動作類(這些動作類都是Action類的子類)。另外控制組件也負責用相應的請求參數填充 Action From(通常稱之為FromBean),并傳給動作類(通常稱之為ActionBean)。動作類實現核心商業邏輯,它可以訪問java bean 或調用EJB。最后動作類把控制權傳給后續的JSP 文件,后者生成視圖。所有這些控制邏輯利用Struts-config.xml文件來配置。
視圖:主要由JSP生成頁面完成視圖,Struts提供豐富的JSP 標簽庫: Html,Bean,Logic,Template等,這有利于分開表現邏輯和程序邏輯。
模型:模型以一個或多個java bean的形式存在。這些bean分為三類:Action Form、Action、JavaBean or EJB。Action Form通常稱之為FormBean,封裝了來自于Client的用戶請求信息,如表單信息。Action通常稱之為ActionBean,獲取從ActionSevlet傳來的FormBean,取出FormBean中的相關信息,并做出相關的處理,一般是調用Java Bean或EJB等。
流程:在Struts中,用戶的請求一般以*.do作為請求服務名,所有的*.do請求均被指向ActionSevlet,ActionSevlet根據Struts-config.xml中的配置信息,將用戶請求封裝成一個指定名稱的FormBean,并將此FormBean傳至指定名稱的ActionBean,由ActionBean完成相應的業務操作,如文件操作,數據庫操作等。每一個*.do均有對應的FormBean名稱和ActionBean名稱,這些在Struts-config.xml中配置。
4.2.2 Struts的基本組件包
整個struts大約有15包,近200個類所組成,而且數量還在不斷的擴展。在此我們不能一一介紹,只能列舉幾個主要的簡要的介紹一下。下表說明了目前struts api中基本的幾個組件包,包括action,actions,taglib。圖片(5)則顯現了這幾個組件包之間的關系。其中action是整個struts framework的核心
org.apache.struts.action |
基本上,控制整個struts framework的運行的核心類、組件都在這個包中,比如我們上面提到的控制器ActionServlet,Action,ActionForm,ActionMapping等等。struts1.1比1.0多了 DynaActionForm 類。增加了動態擴展生成FormBean功能 |
org.apache.struts.actions |
這個包是主要作用是提供客戶的http請求和業務邏輯處理之間的特定適配器轉換功能,而1.0版本中的部分動態增刪FromBean的類,也在struts1.1中被Action包的DynaActionForm組件所取代 |
org.apache.struts.taglib |
這不是一個包,而是是一個客戶標簽類的集合。下面包括Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags這幾個用于構建用戶界面的標簽類。 |
Struts的基本組件關系圖
對于Struts 如何控制、處理客戶請求,讓我們通過對struts的四個核心組件介紹來具體說明。這幾個組件就是:ActionServlet。Action Classes,Action Mapping(此處包括ActionForward),ActionFrom Bean。
4.2.3 Struts ActionServlet
ActionServlet繼承自javax.servlet.http.HttpServlet類,其在Struts framework中扮演的角色是控制器,參看上面的“Struts體系圖”。控制器ActionServlet主要負責將客戶的HTTP請求信息組裝后,根據配置文件的指定描述,轉發到適當的處理器。 按照Servelt的標準,所有得Servlet必須在web配置文件(web.xml)聲明。同樣,ActoinServlet必須在Web Application配置文件(web.xml)中描述,有關配置信息,后面將會介紹。
當用戶向服務器端提交請求的時候,實際上信息是首先發送到控制器ActionServlet,一旦控制器獲得了請求,其就會將請求信息傳交給一些輔助類(help classes)處理。這些輔助類知道如何去處理與請求信息所對應的業務操作。在Struts中,這個輔助類就是org.apache.struts.action.Action。通常開發者需要自己繼承Aciton類,從而實現自己的Action實例。
4.2.4 Struts Action Classes
public ActionForward execute(ActionMapping mapping, ActionForm form, javax.servlet.ServletRequest request, javax.servlet.ServletResponse response) throws java.io.IOException,javax.servlet.ServletException
Action類所作的工作,正如它的名稱一樣,就是具體的業務操作。Action類中最為常用的是execute()方法。
當Controller收到客戶的請求的時候,就會將請求轉移到一個Action實例,然后會調用這個Action實例的execute()方法。Struts Framework為應用系統中的每一個Action類只創建一個實例。所有的用戶都使用這一個實例, Action 類運行在一個多線程的環境中。
注意,客戶自己繼承的Action子類,必須重寫execute()方法,因為Action類在默認情況下是返回null的。
4.2.5 Struts Action Mapping
上面講到了一個客戶請求是如何被控制器轉發和處理的,但是,控制器如何知道什么樣的信息轉發到什么樣的Action類呢?這就需要一些與動作和請求信息相對應的映射配置說明。在struts 中,這些配置映射信息是存儲在特定的XML文件(struts-config.xml)。
<action-mappings> <action path="/logonAction" type="com.test.LogonAction" name="LogonForm" scope="request" input="logoncheck.jsp" validate="false"> <forward name="welcome" path="/welcome.jsp"/> <forward name="failure" path="/logon_failure.jsp "/> </action> </action-mappings>
這些配置信息在系統啟動的時候被讀入內存,供struts framework在運行期間使用。在內存中,每一個<action>元素都與org.apache.struts.action.ActionMapping類的一個實例對應。下表就顯示了一個登陸的配置映射。
Path:這個屬性用來和JSP頁面中,調用<html:form>時的action屬性相對應,它將JSP頁面和處理這個JSP頁面的Action對象對應起來。
Type: 對應的Action子類的完整類名。
Name: 對應的ActionForm的名稱。他與下面將描述的<form-bean>元素的name屬性相應。
Scope:這個屬性表示相對應的ActionForm bean 的scope屬性。它的值可以是“page”、“request”、“session”和“application”。分別對應java bean的“page”、“request”、“session”和“application”屬性。
Input:這個屬性表示如果對應的ActionForm的validate方法返回值的ActionErrors非空,即ActionForm的屬性沒有通過校驗,則跳轉到當前的頁面。
Validate: 是否調用FormBean的validate()方法來驗證,關閉它之后就不會報出錯誤信
息了。True表示需要調用validate方法;false表示不需要調用validate方法。
forward:定義可能的跳轉路徑。Name屬性表示Action類的execute方法中,生成的返回結果時的參數;path表示將要跳轉到的頁面的路徑。
<form-beans> <form-bean name="LoginForm" type="com.test.LoginForm"/> </form-beans>
上面的配置表示:當可以通過/logonAction.do提交請求信息的時候,控制器將信息委托com.test.LogonAction處理。調用LogonAction實例的execute()方法。同時將Mapping實例和所對應的LogonForm Bean信息傳入。其中name=LogonForm,使用的form-bean元素所聲明的ActionForm Bean。有關form-bean的聲明如下顯示。
<form-bean>有兩個屬性:
name :這個ActionForm的名字,他與被JSP頁面中的<HTML:form>元素的name屬性應該是相同的。比如,如果在一個JSP頁面中需要生成一個ActionForm對象,這個對象的名字(就是name屬性)是“LoginForm”,則JSP頁面中的<HTML:form>元素的name屬性也應該是“LoginForm”。
Type :這個ActionForm對象的完整類名。這個屬性和JSP頁面中的<HTML:form>元素的type屬性是相對應的。
在此稍稍說一下有關global-forwards的概念。其在配置文件中描述了整個應用系統可以使用的ActionForward,而不是僅僅是一個特定的Action。
<global-forwards>元素用來表示全局的跳轉頁面。和<action>元素一樣,他有無數個<forward>元素。當一個Action對象的execute方法執行完畢以后,如果他返回的ActionForward對象沒有在這個<action>元素的<forward>子元素中有對應值的話,他將要查找<global-forwards>中的<forward>元素,并跳轉到相應頁面。 <global-forwards> <forward name="logout" path="/logout.do"/> <forward name="error" path="/error.jsp"/> </global-forwards>
<message-resources parameter="test.ApplicationResources"/>
前面我們講過Struts采用屬性文件來保存應用程序的信息,那么,Struts如何知道屬性文件的路徑呢,也在struts-config.xml文件來配置:
<message-resource>元素用來表示ApplicationResources.properties文件的位置。這個元素有一個屬性――parameter,這個屬性用來表示ApplicationResources.properties文件的存放地點,但有意思的是,他是用一個類名來來表示存放路徑的。比如“com. ApplicationResources”是表示存放在WEB-INF/classes / com 路徑下面的ApplicationResources.properties文件。上圖表示的文件路徑為WEB-INF/classes /test/ApplicationResources.properties。
注意:以上所述的這些元素在struts-config.xml文件中的位置也是有先后順序的。它們的順序是:
<form-beans>
< global-forwards >
<actions>
< message-resources >
4.2.6 Struts ActionForm Bean
在上面講解ActionServlet,Action Classes和Action Mapping的時候,我們都提到了ActionForm Bean的概念。ActionForm的主要功能就是為Action的操作提供提交表單相映射的數據。
對于每一個客戶請求,Struts framework在處理ActionForm的時候,一般需要經歷如下幾個步驟:
(1)檢查Action的映射,確定Action中已經配置了對ActionForm的映射
(2)根據name屬性,查找form bean的配置信息
(3)檢查Action的formbean的使用范圍,確定在此范圍下,是否已經有此form bean的實例。
(4)假如當前范圍下,已經存在了此form bean的實例,而是對當前請求來說,是同一種類型的話,那么就重用。
(5)否則,就重新構建一個form bean的實例
(6)form bean的reset()方法備調用
(7)調用對應的setter方法,對狀態屬性賦值
(8)如果validatede的屬性北設置為true,那么就調用form bean的validate()方法。
4.3 例子講解
在這一部分,我將根據一個簡單的例子去詳細的介紹一下struts框架的具體用法。
4.3.1 環境安裝
4.3.1.1 利用Jbuilder8.0 使用Struts 1.1(版本)
目前Jbuilder中默認帶的都是struts1.0版本,我們使用的是struts1.1版本,所以
需要手動的配置相關的類庫
第一步:Struts1.1版本的獲得
可以通過訪問jakarta.apche.org的方式來下載,也可以從我機器的共享目錄拷貝:
IP:150.18.17.150 或機器名zhf
User: guest
PWD: 空
內容: src文件夾下 有 Jarkarta-struts-1.1-rc1
Jarkarta-struts-1.1-rc1-src
Example_struts(例子文件源代碼,可以用Jbuilder直接打開)
Properties(屬性文件使用例子)
Taguse(taglib例子)
還有一些資料。
第二步: Jbuilder配置Struts1.1
首先將Struts1.1文件(包括源碼)拷貝至jbuilder/thirdparty目錄下:
打開jbuilder,選擇tools/configure libraries,在彈出的窗口上點擊new 按鈕
Name :struts1.1
Location :Jbuilder
點擊 Ok,回到剛才的界面,你會看到多出的一項struts1.1,選中它,在右邊的class標簽中點擊Add按鈕,將所帶的所有jar包添加進去,最后的效果如下圖:
然后選擇FrameWork標簽,在其中的Framework上選擇Struts即可。
(這里Jbuilder會自動識別版本的)。
4.3.1.2 利用Jbuilder創建支持Struct1.1的工程:
首先建立一個jbuilder工程文件,名稱可以自己定,這里我使用的easyuse
然后建立一個war文件,名稱可以自己定,這里我使用的easyuse,注意在下面的選項中使用Struts1.1(Struts1.1)Frameworks
這時程序的項目瀏覽器內容如下
我們可以看到一個Struts1.1節點出現在樹形圖中,證明你前面的操作是正確的。
4.3.1.3 利用Jbuilder支持的Stucts對象創建向導:
當我們點擊新建按鈕之后,我們可以看到在 Web標簽下的其他對象。
Struts Converter
ActionForm
Action
JSP from ActionForm
大家可以跟著向導一步一步來操作。
4.3.2 程序編寫
4.3.2.1 任務描述。
createBook.jsp----輸入一本書的標題和頁碼。
bookview.jsp---正常運轉之后,此界面將會獲得createBook.jsp傳來的title參數。
再次提交之后,又回到了creatbook.jsp界面,一個循環過程。
4.3.2.2 ActionForm類
為了便于講述,我在講解內容寫入代碼中。
package test;
import java.util.*;
import org.apache.struts.action.*;
import org.apache.struts.validator.ValidatorForm;
import javax.servlet.http.*;
public class BookActionForm extends ActionForm {
//這里要求 所有的自己編寫的FormBean必須繼承ActionForm
private String title="";
private int pages=0;
//這里的兩個私有屬性字段,對應了createBook.jsp中的兩個文本框,Struts會自動給它們賦
//值的
public void setTitle(String title)
{ this.title=title;}
public String getTitle()
{ return this.title;}
public void setPages(int pages)
{ this.pages=pages;}
public int getPages()
{ return this.pages;}
//Stuts會自動調用ActionForm的validate()方法,來對輸入信息進行校驗。
// validate()方法返回為ActionErrors,這如java的Exception處理機制。
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest)
{
ActionErrors errors =new ActionErrors();
if((title==null)||(title.length()<3))
{
errors.add("Title", new ActionError("error.book.title"));
}
if(pages<1)
{
errors.add("Page",new ActionError("error.book.page"));
}
return errors;
}
public void reset(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {
title = null;
pages = 0;
}
}
4.3.2.3 Struts-config.xml
這是Struts核心文件,Struts-config.xml集中了所有頁面的導航定義。對于大型的WEB項目,通過此配置文件即可迅速把握其脈絡,這不管是對于前期的開發,還是后期的維護或升級都是大有裨益的。掌握Struts-config.xml是掌握Struts的關鍵所在。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
//FormBean的聲明
<form-beans>
<form-bean name="bookActionForm"
type="test.BookActionForm" />
</form-beans>
//公共跳轉
<global-forwards>
<forward name="bookCreated" path="/bookview.jsp"/>
<forward name="first" path="/createBook.jsp"/>
</global-forwards>
//action申明
<action-mappings>
<action path="/createBook"
type="test.BookAction"
attribute="bookActionForm"
name="bookActionForm"
scope="request"
validate="true"
input="/createBook.jsp" />
</action-mappings>
//屬性文件聲明
<message-resources parameter="test.ApplicationResources"/>
</struts-config>
4.3.2.4 Action類
package test;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class BookAction extends Action {
//這里要求 所有的自己編寫的Action子類 必須繼承Action
public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
System.out.println("Start perform("+actionForm+").....");
//我們首先從request中獲得參數
String title=httpServletRequest.getParameter("title");
String strPages=httpServletRequest.getParameter("pages");
System.out.println("getParameter title :"+title);
System.out.println("getParameter Pages:"+strPages);
System.out.println("run in this ----");
//我們再從FormBean中獲得參數
title=((BookActionForm)actionForm).getTitle() ;
strPages=""+ ((BookActionForm)actionForm).getPages() ;
System.out.println(" after BookActionForm ");
System.out.println("BookActionForm title :"+title);
System.out.println("BookActionForm Pages:"+strPages);
//跳轉
return actionMapping.findForward("bookCreated");
}
}
4.3.2.5 應用程序屬性文件的使用
在classes/test 目錄下創建一個ApplicationResources.properties的文件(此路徑在strut-config.xml中定義),打開它,內容如下
index.title=Struts 簡單應用
index.content=這是Struts的一個簡單應用
error.book.title=<li>書名最少要有3個字符</li>
error.book.page=<li>一本書的頁數最少要大于1頁</li>
errors.header=<h3><font color="red">錯誤<UL>
errors.footer=</UL></font><HR>
4.3.2.6 createBook.jsp頁代碼
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:html locale="true">
<head>
<title>
//利用 bean前綴的標簽, key為屬性文件的關鍵字。
<bean:message key="index.title"/>
</title>
</head>
<body bgcolor="#ffffff">
<html:errors/>
<h1><bean:message key="index.content"/></h1>
// createBook.do表示該請求交給了控制起來處理,然后拆分字符串,分解出 createBook,
// 這就是實際的請求。
<html:form action="createBook.do" method="GET">
Title<html:text property="title"/><br/>
Pages<html:text property="pages"/><br/>
<html:submit property="submit"/>
</html:form>
</body>
</html:html>
4.3.2.7 bookview.jsp頁代碼
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<html:html locale="true">
<head>
<html:base/>
<title>
<bean:message key="index.title"/>
</title>
</head>
<body bgcolor="white">
<h1><bean:message key="index.content"/></h1>
<html:form action="createBook" method="GET">
title<html:text property="title"/><br/>
<html:submit property="submit"/>
</html:form>
</body>
</html:html>
4.3.2.8 錯誤處理:
前面的流程已經實現了,下面講一下它的錯誤處理機制。
這個例子程序中,需要用戶輸入標題和頁碼。
當標題的字符數小于3時和頁數小于1時都是不允許的。
ActionForm為接收數據的類,它是錯誤產生的源頭:
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {
ActionErrors errors =new ActionErrors();
if((title==null)||(title.length()<3))
{
//書名的字符數太少了
errors.add("Title", new ActionError("error.book.title"));
}
if(pages<1)
{
//頁數不能小于1
errors.add("Page",new ActionError("error.book.page"));
}
return errors;
}
錯誤提示的描述 applicationResource.properties
error.book.title=<li>書名最少要有3個字符</li>
error.book.page=<li>一本書的頁數最少要大于1頁</li>
errors.header=<h3><font color="red">錯誤<UL>
errors.footer=</UL></font><HR>
對錯誤的選擇處理
createBook.jsp中的處理
<html:errors/>
<html:errors property="Title"/>
<html:errors property="Page"/>