本文为原创,如需转载,请注明作者和出处,谢谢!
本系列教程将详细介绍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. 用户输入产品名称,并根据产品名称进行模糊查询。如果存在符合要求的产品信息。程序会以表格形式显示这些产品的信息,同时显示记录数。如果未查到任何记录,会显示“没有符合要求的记录!”信息。
二、编写程序前的准备工作
在编写程序之前,需要建立一个数据库( struts )和一个表 (t_products) ,建立数据库和表的 SQL 脚本如下所示:
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所示。
![](/images/blogjava_net/nokiaguy/struts1.x.1/3.jpg)
图1
在设置完后,点击Finish按钮关闭对话框。在向samples工程添加支持Struts的功能后,主要对samples工程进行了三个操作。
(1)引入了Struts 1.2 的jar包(在samples的工程树中多了一个Struts 1.2 Libraries节点)。
(2)在WEB-INF目录中添加了一个struts-config.xml文件。文件的默认内容如下面的代码所示:
<! 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的配置,代码如下:
< 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文件,这个文件的内容如下。
< %-- 引用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,代码如下:
< forward name ="newProduct" path ="/mystruts/newProduct.jsp" />
< forward name ="searchProduct" path ="/mystruts/searchProduct.jsp" />
</ global-forwards >
上面的代码中所示的newProduct.jsp和searchProduct.jsp目前并不存在(将在以后实现这两个JSP页面),现在重新输入上述的URL,会得到如图2所示的效果。
![](/images/blogjava_net/nokiaguy/struts1.x.1/4.jpg)
图2
如果想让index.jsp成为默认的JSP页面,可以在web.xml中的<welcome-file-list>节点中加入如下的内容:
这时在IE中只要输入如下的URL就可以访问index.jsp页面了。
http://localhost:8080/samples/mystruts
四、实现添加和查询产品信息页面
在本节中主要实现了用于输入产品信息(newProduct.jsp)和查询产品信息(searchProduct.jsp)的JSP页面。
在newProduct.jsp页面中有一个form,在form中含有三个文本框,用于分别输入产品ID、产品名称和产品价格。
在<samples工程目录>"mystruts目录中建立一个newProduct.jsp文件,代码如下:
<% @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文件,代码如下:
<% @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)
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 类 ) 提供,代码如下: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 文件,代码所示:
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 = " INSERTINTOt_productsVALUES(' " + productID + " ', "
+ " ' " + productName + " ', " + String.valueOf(price) + " ) " ;
PreparedStatementpstmt = conn.prepareStatement(sql);
pstmt.executeUpdate(); // 执行INSERT语句
pstmt.close();
conn.close();
}
catch (Exceptione)
{
throw new Exception(e.getMessage());
}
}
}
在Product类中使用了一个ProductForm类,这个类是一个ActionForm类,它的功能是保存客户端提交的数据。关于这个类将在下面详细介绍。Product类通过构造方法的form参数将客户端提交的数据传入Product类的对象实例中,并在构造方法中验证这些数据,如果发现数据不合法,就会抛出一个异常。当客户端提交的数据合法后,成功建立了一个Product类的对象实例,然后可以通过简单地调用save方法将数据保存到t_products表中。
与 Product 类似,在 <samples 工程目录 >"src 目录中建立一个 SearchProduct.java 文件,代码如下:import java.sql. * ;
import java.util. * ;
import mystruts.actionform. * ;
public class SearchProduct extends util.Struts
{
private ProductFormform;
public SearchProduct(ProductFormform) throws Exception
{
super ();
this .form = form;
}
// 查询产品信息,并通过List返回查询结果
public List < String[] > search() throws Exception
{
List < String[] > result = new LinkedList