本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!
本系列教程將詳細(xì)介紹Struts 1.x的基本原理和使用方法,讀者可以參閱《Struts 2系列教程》來比較Struts 1.x和Struts
2.x的相同點(diǎn)和不同點(diǎn)。
在這篇文章中將以一個(gè)簡(jiǎn)單的例子(mystruts)來演示如何使用MyEclipse來開發(fā)、運(yùn)行Struts程序,并給出了解決ActionForm出現(xiàn)亂碼問題的方法。讀者可以從本文中了解開發(fā)Struts 1.x程序的基本過程。
一、本文給出的程序要實(shí)現(xiàn)什么功能
mystruts是一個(gè)錄入和查詢產(chǎn)品信息的程序。為了方便起見,本例中的產(chǎn)品信息表只包括了產(chǎn)品ID、產(chǎn)品名稱和產(chǎn)品價(jià)格三個(gè)字段。mystruts的主要功能如下:
1. 接受用戶輸入的產(chǎn)品ID、產(chǎn)品名稱和產(chǎn)品價(jià)格。
2. 驗(yàn)證這些字段的合法性。如果某些字段的輸入不合法(如未輸入產(chǎn)品ID),程序會(huì)forward到一個(gè)信息顯示頁(yè),并顯示出錯(cuò)原因。
3. 如果用戶輸入了正確的字段值,程序會(huì)將這些字段值保存到數(shù)據(jù)庫(kù)中,并顯示“保存成功”信息。
4. 用戶輸入產(chǎn)品名稱,并根據(jù)產(chǎn)品名稱進(jìn)行模糊查詢。如果存在符合要求的產(chǎn)品信息。程序會(huì)以表格形式顯示這些產(chǎn)品的信息,同時(shí)顯示記錄數(shù)。如果未查到任何記錄,會(huì)顯示“沒有符合要求的記錄!”信息。
二、編寫程序前的準(zhǔn)備工作
1. 建立數(shù)據(jù)庫(kù)
在編寫程序之前,需要建立一個(gè)數(shù)據(jù)庫(kù)(struts)和一個(gè)表(t_products),建立數(shù)據(jù)庫(kù)和表的SQL腳本如下所示:
# 建立數(shù)據(jù)庫(kù)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 建立一個(gè)支持struts1.x的samples工程
用MyEclipse建立一個(gè)samples工程(Web工程),現(xiàn)在這個(gè)samples工程還不支持Struts1.x(沒有引入相應(yīng)的Struts jar包、struts-config.xml文件以及其他和Struts相關(guān)的配置)。然而,在MyEclipse中這一切并不需要我們手工去加入。而只需要使用MyEclipse的【New Struts Capabilities】對(duì)話框就可以自動(dòng)完成這些工作。
首先選中samples工程,然后在右鍵菜單中選擇【MyEclipse】 > 【New Struts Capabilities】,啟動(dòng)【New Struts Capabilities】對(duì)話框。對(duì)默認(rèn)的設(shè)置需要進(jìn)行如下的改動(dòng):
(1)將Struts specification改為Struts 1.2。
(2)將Base
package for new classes改為struts。
(3)將Default
application resources改為struts.ApplicationResources。
改完后的【New Struts Capabilities】對(duì)話框如圖1所示。
圖1
在設(shè)置完后,點(diǎn)擊Finish按鈕關(guān)閉對(duì)話框。在向samples工程添加支持Struts的功能后,主要對(duì)samples工程進(jìn)行了三個(gè)操作。
(1)引入了Struts 1.2 的jar包(在samples的工程樹中多了一個(gè)Struts 1.2 Libraries節(jié)點(diǎn))。
(2)在WEB-INF目錄中添加了一個(gè)struts-config.xml文件。文件的默認(rèn)內(nèi)容如下面的代碼所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.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動(dòng)作的ActionServlet的配置,代碼如下:
<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工程已經(jīng)完全支持Struts了。讀者可以看到,如果不使用MyEclipse,那么上面所列出的配置文件的內(nèi)容都必須手工輸入。因此,使用MyEclipse來開發(fā)Struts程序可以省去很多配置xml文件的工作。
三、實(shí)現(xiàn)程序的首頁(yè)(index.jsp)
首先在<samples工程目錄>中建立一個(gè)mystruts目錄,然后在<samples工程目錄>" mystruts目錄中建立一個(gè)index.jsp文件,這個(gè)文件的內(nèi)容如下。
<%@ page pageEncoding="GBK"%>
<%-- 引用Struts tag--%>
<%@ 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%">
<%-- 使用Struts tag--%>
<html:link forward="newProduct">錄入產(chǎn)品信息</html:link>
</td>
<td>
<html:link forward="searchProduct">查詢產(chǎn)品信息</html:link>
</td>
</tr>
</table>
</body>
</html>
在MyEclipse中啟動(dòng)Tomcat(如果Tomcat處于啟動(dòng)狀態(tài),在修改完配置文件后,建議在MyEclipse的Servers頁(yè)重新發(fā)布samples工程,以使修改生效)。在IE中輸入如下的URL:
http://localhost:8080/samples/mystruts/index.jsp
我們發(fā)現(xiàn)在輸入上面的URL后,在IE中并未顯示正確的運(yùn)行結(jié)果,而是拋出了如下的異常:
java.net.MalformedURLException:
Cannot retrieve ActionForward named newProduct
這個(gè)異常表明程序并未找到一個(gè)叫newProduct的forward(forward將在后面詳細(xì)地講述)。因此,可以斷定,在JSP中使用forward時(shí),這個(gè)forward必須存在。下面我們來添加index.jsp頁(yè)面中所使用的兩個(gè)forward:newProduct和searchProduct。這兩個(gè)forward分別引向了建立產(chǎn)品信息的頁(yè)面(newProduct.jsp)和查詢產(chǎn)品信息的頁(yè)面(searchProduct.jsp)。我們可以在struts-config.xml文件中<struts-config>節(jié)點(diǎn)中添加兩個(gè)全局的forward,代碼如下:
<global-forwards>
<forward name="newProduct" path="/mystruts/newProduct.jsp" />
<forward name="searchProduct" path="/mystruts/searchProduct.jsp" />
</global-forwards>
上面的代碼中所示的newProduct.jsp和searchProduct.jsp目前并不存在(將在以后實(shí)現(xiàn)這兩個(gè)JSP頁(yè)面),現(xiàn)在重新輸入上述的URL,會(huì)得到如圖2所示的效果。
圖2
如果想讓index.jsp成為默認(rèn)的JSP頁(yè)面,可以在web.xml中的<welcome-file-list>節(jié)點(diǎn)中加入如下的內(nèi)容:
<welcome-file>index.jsp</welcome-file>
這時(shí)在IE中只要輸入如下的URL就可以訪問index.jsp頁(yè)面了。
http://localhost:8080/samples/mystruts
四、實(shí)現(xiàn)添加和查詢產(chǎn)品信息頁(yè)面
在本節(jié)中主要實(shí)現(xiàn)了用于輸入產(chǎn)品信息(newProduct.jsp)和查詢產(chǎn)品信息(searchProduct.jsp)的JSP頁(yè)面。
在newProduct.jsp頁(yè)面中有一個(gè)form,在form中含有三個(gè)文本框,用于分別輸入產(chǎn)品ID、產(chǎn)品名稱和產(chǎn)品價(jià)格。
在<samples工程目錄>"mystruts目錄中建立一個(gè)newProduct.jsp文件,代碼如下:
<%@ page pageEncoding="GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<html>
<head>
<title>錄入產(chǎn)品信息</title>
</head>
<body>
<%-- 向saveProduct動(dòng)作提交產(chǎn)品信息 --%>
<html:form action="saveProduct">
<table width="100%">
<tr>
<td align="center">
產(chǎn)品編號(hào):
<html:text property="productID" maxlength="4" />
<p>
產(chǎn)品名稱:
<html:text property="productName" />
<p>
產(chǎn)品價(jià)格:
<html:text property="price" />
</td>
</tr>
<tr>
<td align="center">
<br>
<html:submit value=" 保存 " />
</td>
</tr>
</table>
</html:form>
</body>
</html>
在searchProduct.jsp頁(yè)面中有一個(gè)form,為了方便起見,在form中只提供了一個(gè)文本框用于對(duì)產(chǎn)品名稱進(jìn)行模糊查詢。在<samples工程目錄>" mystruts目錄中建立一個(gè)searchProduct.jsp文件,代碼如下:
<%@ page pageEncoding="GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<html>
<head>
<title>查詢產(chǎn)品信息</title>
</head>
<body>
<%-- 向searchProduct動(dòng)作提交查詢請(qǐng)求 --%>
<html:form action="searchProduct">
<table width="100%">
<tr>
<td align="center">
產(chǎn)品名稱:
<html:text property="productName" />
</td>
</tr>
<tr>
<td align="center">
<br>
<html:submit value=" 查詢 " />
</td>
</tr>
</table>
</html:form>
</body>
</html>
現(xiàn)在啟動(dòng)Tomcat,并使用如下兩個(gè)URL來訪問newProduct.jsp和searchProduct.jsp:
http://localhost:8080/samples/mystruts/newProduct.jsp
http://localhost:8080/samples/mystruts/searchProduct.jsp
在IE中輸入上面的兩個(gè)URL后,并不能顯示出相應(yīng)的界面,而會(huì)拋出JspException異常,表明未找到saveProduct和searchProduct動(dòng)作。從這一點(diǎn)可以看出,如果在JSP中使用Struts Action,這些Action必須事先在struts-config.xml文件中定義,否則,JSP程序就無法正常訪問。在這兩個(gè)頁(yè)面所使用的動(dòng)作(saveProduct和searchProduct)將會(huì)在下面的部分介紹。
五、通過模型類操作數(shù)據(jù)庫(kù)
在這一節(jié)我們來編寫用于操作數(shù)據(jù)庫(kù)的模型類。由于本例子是Web程序,因此,建議在連接數(shù)據(jù)庫(kù)時(shí)使用數(shù)據(jù)庫(kù)連接池。在<Tomcat安裝目錄>"conf"Catalina"localhost目錄中打開samples.xml文件(如果沒有該文件,則建立一個(gè)samples.xml文件),在<Context>節(jié)點(diǎn)中加入如下的內(nèi)容:
配置連接池(用于連接數(shù)據(jù)庫(kù)struts)
<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"/>
本例中提供了兩個(gè)可以操作數(shù)據(jù)庫(kù)的模型類:Product和SearchProduct。其中Product用于驗(yàn)證由客戶端提交的產(chǎn)品信息,并向t_products表中寫入這些信息。而SearchProduct類用于對(duì)t_products表的product_name字段進(jìn)行模糊查詢,并返回查詢到的產(chǎn)品信息(包括產(chǎn)品ID、產(chǎn)品名稱和產(chǎn)品價(jià)格)。
由于Product和SearchProduct都需要使用數(shù)據(jù)庫(kù)連接池來連接數(shù)據(jù)庫(kù),因此,可以將連接數(shù)據(jù)庫(kù)的工作提出來作為一個(gè)父類(Struts類)提供,代碼如下:
package util;
import java.sql.Connection;
public class Struts
{
protected javax.naming.Context ctx = new javax.naming.InitialContext();
protected javax.sql.DataSource ds;
protected Connection conn;
public Struts() throws Exception
{
ds = (javax.sql.DataSource) ctx.lookup("java:/comp/env/jdbc/struts");
conn = ds.getConnection(); // 從數(shù)據(jù)庫(kù)連接池獲得一個(gè)Connection
}
}
在<samples工程目錄>"src目錄中建立一個(gè)Product.java文件,代碼所示:
package mystruts.model;
import java.sql.*;
import mystruts.actionform.*;
public class Product extends util.Struts
{
private ProductForm form;
public Product(ProductForm form) throws Exception
{
super();
this.form = form;
validate();
}
// 驗(yàn)證客戶端提交的數(shù)據(jù)
public void validate() throws Exception
{
if (form.getProductID().trim().equals(""))
throw new Exception("產(chǎn)品ID不能為空!");
if(form.getProductID().length() > 4)
throw new Exception("產(chǎn)品ID最長(zhǎng)為4位!");
if (form.getProductName().trim().equals(""))
throw new Exception("產(chǎn)品名稱不能為空");
if (Float.compare(form.getPrice(), 0) <= 0)
throw new Exception("產(chǎn)品價(jià)格必須大于0");
}
// 將客戶端提交的產(chǎn)品信息保存到t_products中
public void save() throws Exception
{
try
{
String productID = form.getProductID();
String productName = form.getProductName();
float price = form.getPrice();
String sql = "INSERT INTO t_products VALUES('" + productID + "',"
+ "'" + productName + "'," + String.valueOf(price) + ")";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.executeUpdate(); // 執(zhí)行INSERT語句
pstmt.close();
conn.close();
}
catch (Exception e)
{
throw new Exception(e.getMessage());
}
}
}
在Product類中使用了一個(gè)ProductForm類,這個(gè)類是一個(gè)ActionForm類,它的功能是保存客戶端提交的數(shù)據(jù)。關(guān)于這個(gè)類將在下面詳細(xì)介紹。Product類通過構(gòu)造方法的form參數(shù)將客戶端提交的數(shù)據(jù)傳入Product類的對(duì)象實(shí)例中,并在構(gòu)造方法中驗(yàn)證這些數(shù)據(jù),如果發(fā)現(xiàn)數(shù)據(jù)不合法,就會(huì)拋出一個(gè)異常。當(dāng)客戶端提交的數(shù)據(jù)合法后,成功建立了一個(gè)Product類的對(duì)象實(shí)例,然后可以通過簡(jiǎn)單地調(diào)用save方法將數(shù)據(jù)保存到t_products表中。
與Product類似,在<samples工程目錄>"src目錄中建立一個(gè)SearchProduct.java文件,代碼如下:
package mystruts.model;
import java.sql.*;
import java.util.*;
import mystruts.actionform.*;
public class SearchProduct extends util.Struts
{
private ProductForm form;
public SearchProduct(ProductForm form) throws Exception
{
super();
this.form = form;
}
// 查詢產(chǎn)品信息,并通過List返回查詢結(jié)果
public List<String[]> search() throws Exception
{
List<String[]> result = new LinkedList<String[]>();
String sql = "SELECT * FROM t_products WHERE product_name like '%"
+ form.getProductName() + "%'";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery(); // 開始執(zhí)行SELECT語句
while(rs.next())
{
String[] row = new String[3];
row[0] = rs.getString(1);
row[1] = rs.getString(2);
row[2] = rs.getString(3);
result.add(row);
}
rs.close();
conn.close();
return result;
}
}
在SearchProduct類也使用了ProductForm類,但在SearchProduct中并不會(huì)驗(yàn)證ProductForm對(duì)象實(shí)例中的數(shù)據(jù),而只是將ProductForm對(duì)象作為傳遞查詢請(qǐng)求信息(實(shí)際上只需要產(chǎn)品名稱)的工具而已。
六、實(shí)現(xiàn)控制器
在這一節(jié)要實(shí)現(xiàn)的控制器是基于Struts的Web程序的核心部分之一:控制器實(shí)質(zhì)上也是普通的Java類,但這個(gè)Java類一般要從org.apache.struts.action.Action類繼承。控制器的主要功能是接受并處理從JSP頁(yè)面提交的數(shù)據(jù)、通過模型(Model)和數(shù)據(jù)庫(kù)交互以及forward到相應(yīng)的頁(yè)面(可以是任何頁(yè)面,如html、JSP和Servlet等)。在實(shí)現(xiàn)控制器之前,需要先實(shí)現(xiàn)一個(gè)ActionForm類, 這個(gè)類的作用是保存JSP頁(yè)面提交的數(shù)據(jù)。在<samples工程目錄>"src目錄中建立一個(gè)ProductForm.java文件,代碼如下:
package mystruts.actionform;
import org.apache.struts.action.*;
public class ProductForm extends ActionForm
{
private String productID; // 產(chǎn)品ID
private String productName; // 產(chǎn)品名稱
private float price; // 產(chǎn)品價(jià)格
public String getProductID()
{
return productID;
}
public void setProductID(String productID)
{
this.productID = productID;
}
public String getProductName()
{
return productName;
}
public void setProductName(String productName)
{
this.productName = productName;
}
public float getPrice()
{
return price;
}
public void setPrice(float price)
{
this.price = price;
}
}
從上面的代碼可以看出,ActionForm類一般從org.apache.struts.action.ActionForm類繼承,而且在類中需要按著需要保存的數(shù)據(jù)表字段添加屬性。如產(chǎn)品ID的屬性是productName。在MyEclipse中可以只定義三個(gè)private變量,然后使用MyEclipse的【Source】
> 【Generate Getters and Setters...】功能自動(dòng)產(chǎn)生getter和setter方法。但在給這些屬性取名時(shí)要注意,private變量的名子和數(shù)據(jù)表的字段名沒有直接的關(guān)系,但必須和JSP頁(yè)面中的<html>標(biāo)簽的property屬性值一致,如<html:text property="productName" />表示輸入產(chǎn)品名稱的文本框,其中property屬性的值就是ProductForm類中的productName變量。如果不一致,將會(huì)拋出異常。其他和ProductForm類的屬性對(duì)應(yīng)的<html>標(biāo)簽可以查看上面的代碼。
光有ActionForm類還不夠,還需要在struts-config.xml中的<struts-config>節(jié)點(diǎn)中添加如下的內(nèi)容:
<form-beans>
<form-bean name="saveProductForm" type=" mystruts.actionform.ProductForm" />
<form-bean name="searchProductForm" type="mystruts.actionform.ProductForm" />
</form-beans>
上面的代碼所配置的兩個(gè)ActionForm實(shí)際上指的是同一個(gè)ProductForm類,但這個(gè)ProductForm類在后面要講的兩個(gè)動(dòng)作里都要使用,為了更容易理解,為這個(gè)ProductForm起了兩個(gè)不同的別名(saveProductForm和searchProductForm)。
下面來實(shí)現(xiàn)saveProduct動(dòng)作的代碼。Struts Action類必須一般從org.apache.struts.action.Action類繼承。一般在Struts
Action類需要覆蓋Action類的execute方法。這個(gè)方法有每次客戶端訪問Struts Action時(shí)調(diào)用。我們可以在方法中處理客戶端提交的數(shù)據(jù),訪問數(shù)據(jù)庫(kù)等工作。這個(gè)方法返回一個(gè)ActionForward類型的值,表明在執(zhí)行完execute后,要forward到的頁(yè)面。描述saveProduct動(dòng)作的類叫SaveProductAction。代碼如下:
package mystruts.action;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import mystruts.actionform.*;
import mystruts.model.*;
public class SaveProductAction extends Action
{
// 在客戶端訪問saveProduct動(dòng)作時(shí)執(zhí)行該方法
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
{
ProductForm saveProductForm = (ProductForm) form;
try
{
Product product = new Product(saveProductForm);
product.save(); // 保存產(chǎn)品信息
request.setAttribute("info", "保存成功!");
}
catch (Exception e)
{
request.setAttribute("info", e.getMessage());
}
return mapping.findForward("save");
}
}
在SaveProductAction類中使用了模型類Product驗(yàn)證并保存產(chǎn)品信息。并將操作結(jié)果信息保存在request的屬性中,key為“info”。在execute的最后,使用了ActionMapping類的findForward方法在struts-config.xml中尋找一個(gè)叫“save”的forward。這個(gè)forward是一個(gè)JSP頁(yè),用于顯示是否將產(chǎn)品信息保存成功的信息。為了可以在struts-config.xml中查找這個(gè)forward,需要在struts-config.xml的<action-mappings>節(jié)點(diǎn)中加入如下的內(nèi)容。
<action name="saveProductForm" path="/saveProduct"scope="request" type=" mystruts.action.SaveProductAction">
<forward name="save" path="/mystruts/save.jsp" />
</action>
從上面的代碼可以看出,那個(gè)用于顯示保存狀態(tài)信息的JSP頁(yè)面叫save.jsp。在<samples工程目錄>"mystruts目錄中建立一個(gè)save.jsp文件,代碼如下:
<%@ page pageEncoding="GBK"%>
${requestScope.info}
在IE中輸入如下的URL:
http://localhost:8080/samples/mystruts/newProduct.jsp
在文本框中輸入相應(yīng)的信息后,點(diǎn)“保存”按鈕,如果輸入的數(shù)據(jù)是合法的,就會(huì)將數(shù)據(jù)保存在t_products中,否則會(huì)顯示出錯(cuò)的原因。 searchProduct動(dòng)作的實(shí)現(xiàn)和saveProduct差不多,也會(huì)為三步:實(shí)現(xiàn)動(dòng)作類(SearchProductAction)、在struts-config.xml中添加配置信息和實(shí)現(xiàn)用于顯示查詢結(jié)果的JSP文件。下面的代碼分別顯示了這三步所要編寫的代碼。
SearchProductAction.java
package mystruts.action;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import mystruts.actionform.*;
import mystruts.model.*;
import java.util.*;
public class SearchProductAction extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
{
ProductForm searchProductForm = (ProductForm) form;
try
{
SearchProduct searchProduct = new SearchProduct(searchProductForm);
List<String[]> result = searchProduct.search(); // 查詢產(chǎn)品信息
if (result.size() > 0) // 有符合條件的產(chǎn)品信息
{
request.setAttribute("result", result);
request.setAttribute("info", "記錄數(shù):" + String.valueOf(result.size()));
}
else // 沒有查到任何產(chǎn)品信息
request.setAttribute("info", "沒有符合要求的記錄!");
}
catch (Exception e)
{
request.setAttribute("info", e.getMessage());
}
return mapping.findForward("search");
}
}
在struts-config.xml中配置searchProduct動(dòng)作
<action name="searchProductForm" path="/searchProduct" scope="request" type="mystruts.action.SearchProductAction">
<forward name="search" path="/mystruts/search.jsp" />
</action>
search.jsp
<%@ page pageEncoding="GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<body>
<%-- 從request的result中取出查詢結(jié)果 --%>
<c:set var="result" value="${requestScope.result}" />
<table width="100%">
<tr align="center">
<td>
${requestScope.info}
</td>
</tr>
<tr align="center">
<td>
<logic:present name="result">
<table border="1">
<tr align="center">
<td> 產(chǎn)品ID </td>
<td> 產(chǎn)品名稱 </td>
<td> 價(jià)格 </td>
</tr>
<logic:iterate id="row" name="result">
<tr> <td> ${row[0]} </td>
<td> ${row[1]} </td>
<td> ${row[2]} </td>
</tr>
</logic:iterate>
</table>
</logic:present>
</td>
</tr>
</table>
</body>
</html>
在IE中輸入如下的URL:
http://localhost:8080/samples/%20mystruts/searchProduct.jsp
在“產(chǎn)品名稱”文本框中輸入產(chǎn)品名稱的一部分,程序就會(huì)查詢出所有包含輸入的產(chǎn)品名稱的產(chǎn)品信息,并將結(jié)果顯示出來。
七、解決ActionForm的亂碼問題
到現(xiàn)在為止,程序的功能部分已經(jīng)全部實(shí)現(xiàn)完了。但還存在一個(gè)問題。當(dāng)我們?cè)诋a(chǎn)品名稱中輸入中文時(shí),雖然將客戶端提交的數(shù)據(jù)成功保存到數(shù)據(jù)庫(kù)中,但是在t_products表中的product_name字段顯示的都是亂碼。產(chǎn)生這個(gè)問題的原因只有一個(gè),就是客戶端提交的數(shù)據(jù)的編碼格式和數(shù)據(jù)庫(kù)的編碼格式不一致造成的。當(dāng)然,解決這個(gè)問題的方法有很多,但筆者認(rèn)為最容易的就是使用過濾器。所謂過濾器,就是在客戶端提交數(shù)據(jù)后,在交由服務(wù)端處理之前所執(zhí)行的一段服務(wù)端代碼(一般為Java代碼)。一個(gè)過濾器是一個(gè)實(shí)現(xiàn)javax.servlet.Filter接口的類。在本例中要使用的過濾器類叫EncodingFilter,實(shí)現(xiàn)代碼如下:
EncodingFilter.java
package filter;
import java.io.IOException;
import javax.servlet.*;
public class EncodingFilter implements Filter
{
public void destroy() { }
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
request.setCharacterEncoding("GBK"); // 將客戶端提交的數(shù)據(jù)設(shè)為GBK編碼格式
// 繼續(xù)處理客戶端提交的數(shù)據(jù),如果不寫這條語句,Servlet引擎將不會(huì)處理所過濾的頁(yè)面
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException { }
}
Filter接口的doFilter方法是過濾器的核心方法。其中FilterChain類的doFilter方法允許繼續(xù)處理客戶端提交的數(shù)據(jù)。我們還可以使用這個(gè)方法來臨時(shí)關(guān)閉Web站點(diǎn)的某個(gè)或全部的頁(yè)面(根據(jù)過濾器的設(shè)置而定)。由于本書的數(shù)據(jù)庫(kù)使用的是GBK編碼格式,因此,需要使用ServletRequest的setCharacterEncoding方法將客戶端提交的數(shù)據(jù)也設(shè)為GBK編碼格式。
除了實(shí)現(xiàn)過濾器類,我們還需要在web.xml中的<web-app>節(jié)點(diǎn)加入如下的配置信息才能使過濾器生效:
在web.xml中配置過濾器
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>
filter.EncodingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在重新啟動(dòng)Tomcat后,重新輸入一條帶中文的產(chǎn)品信息,看看是否可以將中文保存在數(shù)據(jù)庫(kù)中?
下一篇:Struts1.x系列教程(2):簡(jiǎn)單的數(shù)據(jù)驗(yàn)證
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining