本文爲原創,如需轉載,請註明作者和出處,謝謝!
本系列教程將詳細介紹Struts 1.x的基本原理和使用方法,讀者可以參閱《Struts 2系列教程》來比較Struts 1.x和Struts 2.x的相同點和不同點。
在這篇文章中將以一個簡單的例子(mystruts)來演示如何使用MyEclipse來開發、運行Struts程序,並給出瞭解決ActionForm出現亂碼問題的方法。讀者可以從本文中瞭解開發Struts 1.x程序的基本過程。
一、本文給出的程序要實現什麼功能
mystruts是一個錄入和查詢產品信息的程序。爲了方便起見,本例中的產品信息表只包括了產品ID、產品名稱和產品價格三個字段。mystruts的主要功能如下:
1. 接受用戶輸入的產品ID、產品名稱和產品價格。
2. 驗證這些字段的合法性。如果某些字段的輸入不合法(如未輸入產品ID),程序會forward到一個信息顯示頁,並顯示出錯原因。
3. 如果用戶輸入了正確的字段值,程序會將這些字段值保存到數據庫中,並顯示「保存成功」信息。
4. 用戶輸入產品名稱,並根據產品名稱進行模糊查詢。如果存在符合要求的產品信息。程序會以表格形式顯示這些產品的信息,同時顯示記錄數。如果未查到任何記錄,會顯示「沒有符合要求的記錄!」信息。
二、編寫程序前的準備工作
1. 建立數據庫
在編寫程序之前,需要建立一個數據庫(
struts
)和一個表
(t_products)
,建立數據庫和表的
SQL
腳本如下所示:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
#建立數據庫struts
CREATE
DATABASE
IF
NOT
EXISTS
struts
DEFAULT
CHARACTER
SET
GBK;
#建立表t_products
CREATE
TABLE
IF
NOT
EXISTS
struts.t_products(
product_id
varchar
(
4
)
NOT
NULL
,
product_name
varchar
(
50
)
NOT
NULL
,
price
float
NOT
NULL
,
PRIMARY
KEY
(product_id)
)ENGINE
=
InnoDB
DEFAULT
CHARSET
=
gbk;
2建立一個支持struts1.x的samples工程
用MyEclipse建立一個samples工程(Web工程),現在這個samples工程還不支持Struts1.x(沒有引入相應的Struts jar包、struts-config.xml文件以及其他和Struts相關的配置)。然而,在MyEclipse中這一切並不需要我們手工去加入。而只需要使用MyEclipse的【New Struts Capabilities】對話框就可以自動完成這些工作。
首先選中samples工程,然後在右鍵菜單中選擇【MyEclipse】 > 【New Struts Capabilities】,啓動【New Struts Capabilities】對話框。對默認的設置需要進行如下的改動:
(1)將Struts specification改爲Struts 1.2。
(2)將Base package for new classes改爲struts。
(3)將Default application resources改爲struts.ApplicationResources。
改完後的【New Struts Capabilities】對話框如圖1所示。
圖1
在設置完後,點擊Finish按鈕關閉對話框。在向samples工程添加支持Struts的功能後,主要對samples工程進行了三個操作。
(1)引入了Struts 1.2 的jar包(在samples的工程樹中多了一個Struts 1.2 Libraries節點)。
(2)在WEB-INF目錄中添加了一個struts-config.xml文件。文件的默認內容如下面的代碼所示:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<?
xmlversion="1.0"encoding="UTF-8"
?>
<!
DOCTYPEstruts-configPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd"
>
<
struts-config
>
<
data-sources
/>
<
form-beans
/>
<
global-exceptions
/>
<
global-forwards
/>
<
action-mappings
/>
<
message-resources
parameter
="struts.ApplicationResources"
/>
</
struts-config
>
(3)在WEB-INF中的web.xml文件中添加了處理Struts動作的ActionServlet的配置,代碼如下:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<
servlet
>
<
servlet-name
>
action
</
servlet-name
>
<
servlet-class
>
org.apache.struts.action.ActionServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
config
</
param-name
>
<
param-value
>
/WEB-INF/struts-config.xml
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
3
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
detail
</
param-name
>
<
param-value
>
3
</
param-value
>
</
init-param
>
<
load-on-startup
>
0
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
action
</
servlet-name
>
<
url-pattern
>
*.do
</
url-pattern
>
</
servlet-mapping
>
到目前爲止,samples工程已經完全支持Struts了。讀者可以看到,如果不使用MyEclipse,那麼上面所列出的配置文件的內容都必須手工輸入。因此,使用MyEclipse來開發Struts程序可以省去很多配置xml文件的工作。
三、實現程序的首頁(index.jsp)
首先在<samples工程目錄>中建立一個mystruts目錄,然後在<samples工程目錄>" mystruts目錄中建立一個index.jsp文件,這個文件的內容如下。
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<
%@page
pageEncoding
="GBK"
%
>
<
%--
引用Strutstag--%
>
<
%@taglib
uri
="http://struts.apache.org/tags-html"
prefix
="html"
%
>
<
html
>
<
head
>
<
title
>
主界面
</
title
>
</
head
>
<
body
>
<
table
align
="center"
cellpadding
="10"
width
="100%"
>
<
tr
>
<
td
align
="right"
width
="50%"
>
<
%--
使用Strutstag--%
>
<
html:link
forward
="newProduct"
>
錄入產品信息
</
html:link
>
</
td
>
<
td
>
<
html:link
forward
="searchProduct"
>
查詢產品信息
</
html:link
>
</
td
>
</
tr
>
</
table
>
</
body
>
</
html
>
在MyEclipse中啓動Tomcat(如果Tomcat處於啓動狀態,在修改完配置文件後,建議在MyEclipse的Servers頁重新發布samples工程,以使修改生效)。在IE中輸入如下的URL:
http://localhost:8080/samples/mystruts/index.jsp
我們發現在輸入上面的URL後,在IE中並未顯示正確的運行結果,而是拋出瞭如下的異常:
java.net.MalformedURLException: Cannot retrieve ActionForward named newProduct
這個異常表明程序並未找到一個叫newProduct的forward(forward將在後面詳細地講述)。因此,可以斷定,在JSP中使用forward時,這個forward必須存在。下面我們來添加index.jsp頁面中所使用的兩個forward:newProduct和searchProduct。這兩個forward分別引向了建立產品信息的頁面(newProduct.jsp)和查詢產品信息的頁面(searchProduct.jsp)。我們可以在struts-config.xml文件中<struts-config>節點中添加兩個全局的forward,代碼如下:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<
global-forwards
>
<
forward
name
="newProduct"
path
="/mystruts/newProduct.jsp"
/>
<
forward
name
="searchProduct"
path
="/mystruts/searchProduct.jsp"
/>
</
global-forwards
>
上面的代碼中所示的newProduct.jsp和searchProduct.jsp目前並不存在(將在以後實現這兩個JSP頁面),現在重新輸入上述的URL,會得到如圖2所示的效果。
圖2
如果想讓index.jsp成爲默認的JSP頁面,可以在web.xml中的<welcome-file-list>節點中加入如下的內容:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<
welcome-file
>
index.jsp
</
welcome-file
>
這時在IE中只要輸入如下的URL就可以訪問index.jsp頁面了。
http://localhost:8080/samples/mystruts
四、實現添加和查詢產品信息頁面
在本節中主要實現了用於輸入產品信息(newProduct.jsp)和查詢產品信息(searchProduct.jsp)的JSP頁面。
在newProduct.jsp頁面中有一個form,在form中含有三個文本框,用於分別輸入產品ID、產品名稱和產品價格。在<samples工程目錄>"mystruts目錄中建立一個newProduct.jsp文件,代碼如下:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<%
@pagepageEncoding
=
"
GBK
"
%>
<%
@tagliburi
=
"
http://struts.apache.org/tags-html
"
prefix
=
"
html
"
%>
<
html
>
<
head
>
<
title
>
錄入產品信息
</
title
>
</
head
>
<
body
>
<%
--
向saveProduct動作提交產品信息
--
%>
<
html:form
action
="saveProduct"
>
<
table
width
="100%"
>
<
tr
>
<
td
align
="center"
>
產品編號:
<
html:text
property
="productID"
maxlength
="4"
/>
<
p
>
產品名稱:
<
html:text
property
="productName"
/>
<
p
>
產品價格:
<
html:text
property
="price"
/>
</
td
>
</
tr
>
<
tr
>
<
td
align
="center"
>
<
br
>
<
html:submit
value
="保存"
/>
</
td
>
</
tr
>
</
table
>
</
html:form
>
</
body
>
</
html
>
在searchProduct.jsp頁面中有一個form,爲了方便起見,在form中只提供了一個文本框用於對產品名稱進行模糊查詢。在<samples工程目錄>" mystruts目錄中建立一個searchProduct.jsp文件,代碼如下:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<%
@pagepageEncoding
=
"
GBK
"
%>
<%
@tagliburi
=
"
http://struts.apache.org/tags-html
"
prefix
=
"
html
"
%>
<
html
>
<
head
>
<
title
>
查詢產品信息
</
title
>
</
head
>
<
body
>
<%
--
向searchProduct動作提交查詢請求
--
%>
<
html:form
action
="searchProduct"
>
<
table
width
="100%"
>
<
tr
>
<
td
align
="center"
>
產品名稱:
<
html:text
property
="productName"
/>
</
td
>
</
tr
>
<
tr
>
<
td
align
="center"
>
<
br
>
<
html:submit
value
="查詢"
/>
</
td
>
</
tr
>
</
table
>
</
html:form
>
</
body
>
</
html
>
現在啓動Tomcat,並使用如下兩個URL來訪問newProduct.jsp和searchProduct.jsp:
http://localhost:8080/samples/mystruts/newProduct.jsp
http://localhost:8080/samples/mystruts/searchProduct.jsp
在IE中輸入上面的兩個URL後,並不能顯示出相應的界面,而會拋出JspException異常,表明未找到saveProduct和searchProduct動作。從這一點可以看出,如果在JSP中使用Struts Action,這些Action必須事先在struts-config.xml文件中定義,否則,JSP程序就無法正常訪問。在這兩個頁面所使用的動作(saveProduct和searchProduct)將會在下面的部分介紹。
五、通過模型類操作數據庫
在這一節我們來編寫用於操作數據庫的模型類。由於本例子是
Web
程序,因此,建議在連接數據庫時使用數據庫連接池。在
<Tomcat
安裝目錄
>"conf"Catalina"localhost
目錄中打開
samples.xml
文件(如果沒有該文件,則建立一個
samples.xml
文件),在
<Context>
節點中加入如下的內容:
配置連接池(用於連接數據庫struts)
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
<
Resource
name
="jdbc/struts"
auth
="Container"
type
="javax.sql.DataSource"
driverClassName
="com.mysql.jdbc.Driver"
url
="jdbc:mysql://localhost:3306/struts?characterEncoding=GBK"
username
="root"
password
="1234"
maxActive
="200"
maxIdle
="50"
maxWait
="3000"
/>
本例中提供了兩個可以操作數據庫的模型類:Product和SearchProduct。其中Product用於驗證由客戶端提交的產品信息,並向t_products表中寫入這些信息。而SearchProduct類用於對t_products表的product_name字段進行模糊查詢,並返回查詢到的產品信息(包括產品ID、產品名稱和產品價格)。
由於
Product
和
SearchProduct
都需要使用數據庫連接池來連接數據庫,因此,可以將連接數據庫的工作提出來作爲一個父類
(Struts
類
)
提供,代碼如下:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
package
util;
import
java.sql.Connection;
public
class
Struts
{
protected
javax.naming.Contextctx
=
new
javax.naming.InitialContext();
protected
javax.sql.DataSourceds;
protected
Connectionconn;
public
Struts()
throws
Exception
{
ds
=
(javax.sql.DataSource)ctx.lookup(
"
java:/comp/env/jdbc/struts
"
);
conn
=
ds.getConnection();
//
從數據庫連接池獲得一個Connection
}
}
在
<samples
工程目錄
>"src
目錄中建立一個
Product.java
文件,代碼所示:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
package
mystruts.model;
import
java.sql.
*
;
import
mystruts.actionform.
*
;
public
class
Product
extends
util.Struts
{
private
ProductFormform;
public
Product(ProductFormform)
throws
Exception
{
super
();
this
.form
=
form;
validate();
}
//
驗證客戶端提交的數據
public
void
validate()
throws
Exception
{
if
(form.getProductID().trim().equals(
""
))
throw
new
Exception(
"
產品ID不能爲空!
"
);
if
(form.getProductID().length()
>
4
)
throw
new
Exception(
"
產品ID最長爲4位!
"
);
if
(form.getProductName().trim().equals(
""
))
throw
new
Exception(
"
產品名稱不能爲空
"
);
if
(Float.compare(form.getPrice(),
0
)
<=
0
)
throw
new
Exception(
"
產品價格必須大於0
"
);
}
//
將客戶端提交的產品信息保存到t_products中
public
void
save()
throws
Exception
{
try
{
StringproductID
=
form.getProductID();
StringproductName
=
form.getProductName();
float
price
=
form.getPrice();
Stringsql
=
"