WebWork入门教程--创建你第一个WebWork action
摘要
本文,摘录了Manning出版社出版,Patrick Lightbody 和 Jason Carreira所著《WebWork in Action》中关于怎样创建WebWork action和它的视图以及将两者柔和在一起的部分。
一个action是一块代码,当特定的URL被请求时,他会被执行。Action被执行后将可视化的显示一个执行结果。一个结果可以是HTML页面,也可是PDf文件、EXCEL表格,或者甚至可以是Java applet 窗口。本文我们将主要关注HTML结果,因为这对于web来说是最普遍和特别的。正如牛顿第三定律所讲的一个作用力一定有一个反作用力(从技术上一个action不是一定得有一个结果,但一般都这样做)尽管他们之间的关系不总是"相等以及相反",但是最终的结果总是反映WebWork中被执行的action。
假设你要建一个简单的"Hello, World"例子,当用户访问URL: http://localhost/helloWorld.action,这个例子会显示Hello, World消息。由于你将WebWork的Servlet 映射到.action,你需要一个名称叫helloWorld的action。为创建"Hello, World"例子,需做如下三件事情:
1.创建一个action类:HelloWorld;
2.创建一个结果页面:hello.jsp;
3.配置action和结果页面;
让我们开始编写创建welcome消息的代码。
用WebWork的方法说hello
创建如下列表所示的action类:
HelloWorld.java
package ch2.example1;
import com.opensymphony.xwork.Action;
public class HelloWorld implements Action {
private String message;
public String execute() {
message = "Hello, World!\n";
message += "The time is:\n";
message += System.currentTimeMillis();
return SUCCESS;
}
public String getMessage() {
return message;
}
}
特别需要注意的是HelloWorld类实现了Action接口。所有WebWork action都必须实现Action接口,该接口提供了一个execute()方法,当执行这个action时,WebWork会调用这个方法。
在execute()里面,用当前时间和“Hello, World”构造一个消息。通过JavaBean风格的getter方法getMessage()暴露这个message字段。这允许message通过JSP标签被检索和显示给用户。
最后,execute()方法返回SUCCESS(一个成功的字符串常量), 指示action成功执行。这个常量和其他常量,例如INPUT、ERROR是定义在Action接口里面的。所有WebWork action都必须返回一个结果代码-一个用于指示action执行结果的字符串。
要注意的是结果代码并不总是意味着被执行,尽管一般情况下是这样的。
你很快将看到这些结果代码通过映射而最终能够显示给用户的结果。既然action已经被创建,下一个逻辑步骤是创建一个HTML来显示这个message。
将结果显示到Web浏览器
WebWork允许用许多不同的方法显示action的输出结果给用户,但最简单通用的办法是显示HTML给Web浏览器。其它技术,包括显示一个PDF报表或者逗号分割的CSV表格。
你能简单地创建JSP页面生成HTML视图:
<%@ taglib prefix="ww" uri="webwork" %>
<html>
<head>
<title>Hello Page</title>
</head>
<body>
The message generated by my first action is:
<ww:property value="message"/>
</body>
</html>
第一行的Tag定义映射前缀ww到URI webwork。(注意URI跟web.xml文件里面的URI是一样的)前缀ww表明所有WebWork标签以ww:开始。
如你所看到的那样,这是一个使用WebWork定制标签:property的简单JSP页面。Property标签接受一个value属性并从action取得那个表达式的值。由于你在那action里面创建了一个getMessage()方法,所以message属性值决定了getMessage()方法调用的返回值。将该文件命名为hello.jsp并保存在您的Web应用root目录下。
配置您新创建的action
既然已经创建了action类和视图jsp页面,最后一步是将两者联系起来。你可以通过配置这个action到一个特定的URL并且映射SUCCESS到你刚才创建的jsp做到。回想你创建框架布局时候,就已经生成了一个几乎是空的xwork.xml文件。你现在向xwork.xml文件添加一些有意义的东西,看看最终WebWork action的工作。
配置WebWork action时,必须知道以下三点:
action的全名,包括包名和类名;
action的URL;
那个action的所有可能返回的结果代码;
正如你所知,这个action的充分名称是ch2.example1.HelloWorld。URL可以是你喜欢的东西,这里我们使用/helloWorld.action。这个action的唯一可能的返回代码是SUCCESS。
有了这些信息,让我们修改xwork.xml文件来定义这个action:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="default" extends="webwork-default">
<default-interceptor-ref name="completeStack"/>
<action name="helloWorld"
class="ch2.example1.HelloWorld">
<result name="success">hello.jsp</result>
</action>
</package>
</xwork>
这个文件里面,你现在已经将action的逻辑名称(helloWorld)跟你希望执行的哪个action类联系起来了。所以任何一个针对 /helloWorld.action 的HTTP请求将调用您的action类。你也可以将action执行的结果代码SUCCESS ("success"的字符创常量)和你创建的用来显示message的jsp页面联系起来。
保存With xwork.xml,编译和拷贝action类到WEB-INF/ classes目录下,并且将hello.jsp添加到Web应用root目录下,准备启动应用服务器来试试这个新的action。怎样启动、停止、部署Web应用,请参考你的应用服务器文档。
已经完成了所有步骤了! 现在你可以在你的浏览器地址栏中输入http://localhost/helloWorld.action 来看看最终的效果。如图Figure 1。 (URL是否包括一个象8080一样的端口号,取决于servlet 容器和配置。)
![image](http://www.matrix.org.cn/resource/upload/forum/2006_07_19_234054_sotdLpWiXF.jpg)
Figure 1. The first "Hello World" action
如你所见,这并不令人兴奋。所以让我们添加一些有意思的事情。你可以定制一个action,让用户输入他们的名字,然后生成问候语。目前为止,你看到action是只读的;现在你将学习怎样处理输入和可读写的action。
处理输入
你已经知道了怎样构建一个简单的action,现在让我们来整合一下并添加个性化消息的功能。你将基于现有代码构建。首先,创建一个要求用户输入名称的页面。创建下面的文件并命名为name.jsp,放在与hello.jsp相同的目录:
<html>
<head>
<title>Enter your name</title>
</head>
<body>
Please enter your name:
<form action="helloWorld.action">
<input type="textfield"
name="name"/>
<input type="submit"/>
</form>
</body>
</html>
注意那个表单被提交到helloWorld.action-跟用来显示前一个例子的location一样。因为你在前一个例子基础上扩展,所以继续使用这个location。另外重要的一点是文本输入框的名字叫做name。正如message是你用来像是消息的属性一样,name是你用来输入用户名称的属性。
下一步,修改HelloWorld action来构造一个个化的消息。新代码如下:
package ch2.example1;
import com.opensymphony.xwork.Action;
public class HelloWorld implements Action {
private String message;
private String name;
public String execute() {
message = "Hello, " + name + "!\n";
message += "The time is:\n";
message += System.currentTimeMillis();
return SUCCESS;
}
public String getMessage() {
return message;
}
public void setName(String name) {
this.name = name;
}
public String getName(){
return this.name;
}
}
相对于前一个例子,这段代码添加了两个东西。第一个是在action里面添加了name属性和该属性的get/set方法。这个属性是跟name,jsp页面的文本输入框的名字是严格匹配的。在execute()方法里面,你也用name构建了一个个性化的消息。在WebWork里面,value总是在execute()方法调用前被设置(通过setXxx()方法,例如setName())。这意味着你可以在execute()方法里面使用那个变量。
编译action类,启动应用服务器。在浏览器中输入:http://localhost/name.jsp,键入一个名称,现在看到消息是个性化的。如图2
![image](http://www.matrix.org.cn/resource/upload/forum/2006_07_19_234337_xhAdmqblsy.jpg)
图 2. 新的消息是个性化的。 这里我们使用Patrick作为输入。
就象它很简单一样,问题也可能容易出现。例如,假设用户没有输入任何数据将会怎么样呢?问候语将以"Hello, !"终止。与其显示一个丑陋难看的消息,还不如回到原始页面,要求用户输入一个真是的姓名。让我们在这个action中添加一些高级控制流。
高级控制流
因为你想要action不是显示消息结果(hello.jsp)就是显示原始输入表单(name.jsp),所以你必须在xwork.xml文件中定义另外一个结果。可以通过改变action的入口做到,如下:
<action name="helloWorld"
class="ch2.example1.HelloWorld">
<result name="success">hello.jsp</result>
<result name="input">name.jsp</result>
</action>
现在,如果HelloWorld action的execute() 返回字符串“input”(在方法中也被定义成常量INPUT),那么action的执行结果将是name.jsp而不是hello.jsp。 为个这个例子再加一点有意思的事情,让我们不允许在文本输入框name中输入“World“。在修改action的execute()以支持这个检查功能。代码如下:
public String execute() {
if (name == null || "".equals(name)
|| "World".equals(name)) {
return INPUT;
}
message = "Hello," + name + "!\n";
message += "The time is:\n";
message += System.currentTimeMillis();
}
若名称没有通过你校验规则的校验,你返回INPUT,不生成消息字符串。只需几行代码就增加了action的控制流。然而,这样作显然还是不足够的,因为:
1、当你返回到INPUT时,用户不明白为什么他会返回这个页面。根本上是因为没有错误提示信息。
2、用户不知道他的原始输入值。他或许什么也没有输,或许输入的是个单词。最好能显示用户的原始输入值。
为处理这两个方面的考虑,让我们修改INPUT结果来显示错误信息。你可以从success结果重用message属性。然后,添加逻辑显示错误信息,同时也使文本输入字段显示发生错误时的先前输入值。修改name.jsp,如下:
<%@ taglib prefix="ww" uri="webwork" %>
<html>
<head>
<title>Enter your name</title>
</head>
<body>
<ww:if test="message != null">
<font color="red">
<ww:property value="message"/>
</font>
</ww:if>
Please enter your name:
<form action="/helloWorld.action">
<input type="textfield"
name="name"
value="<ww:property value="name"/>"/>
<input type="submit"/>
</form>
</body>
</html>
这段代码给jsp添加了两个有意义的事情。首先,当错误消息存在时,以红色字体输出它。你可以用ww:if来测试错误消息是否存在;若存在,则输出它。如果用户直接访问这个页面,那么条件测试失败,并且不会报告错误信息。
第二,你添加了value属性到文本输入框。这个属性定义了页面首次装入时要显示的缺省值。如果属性没有找到时,由于ww:property标签返回一个空字符串,所以也能产生想要的行为。Action被提交一次后,这个属性便存在。正如这样,如果INPUT结果发生的话,将显示前一次输入的值。
最后,让我们再次修改action的execute()方法。这次,你将确保在action用INPUT代码返回前将错误消息设置在message里面。新的方法如下:
public String execute() {
if (name == null || "".equals(name)
|| "World".equals(name)) {
message = "Blank names or names of 'World' are not allowed!";
return INPUT;
}
message = "Hello," + name + "!\n";
message += "The time is:\n";
message += System.currentTimeMillis();
return SUCCESS;
}
这里,最值得注意的是如果校验失败,则execute()方法不会以INPUT返回。
有了这些修改,你就可以准备尝试一下新的行为特性。启动你的应用服务器,在地址栏中输入http://localhost/name.jsp。在文本输入字段键入World并提交表单,你可以看到屏幕显示如图3。
![image](http://www.matrix.org.cn/resource/upload/forum/2006_07_19_234733_rReqsBefXt.jpg)
图3. 无效名称输入时的"Hello World" 例子。
这种控制流,校验和错误报告常常是Web应用所需的。与其让开发者处理那些任务,不如让WebWork为你提供帮助。
关于作者
作为Jive软件专业服务组织的领导者,Patrick Lightbody已经为各种技术公司工作过,有象Cisco那样的巨人公司,也有象硅谷刚起步那样的小公司。他是《Java Open Source Programming》一书的作者并且将它的业余时间贡献给了OpenSymphony的各种工程,包括WebWork和OSWorkflow。Lightbody虽然在成长在硅谷中心,现在却住在波特兰。
Jason Carreira从事J2EE应用开发和架构设计已经六年了。过去的五年里,他重新设计和构建了企业金融软件产品。近来加入了ePlus,那里他从事于下一代eProcurement解决方案。业余时间,Carreira是XWork命令模式框架和WebWork MVC Web框架的核心开发者。他和妻子以及三个孩子居住在纽约的罗彻斯特。
资源
---论文摘录了《WebWork in Action》一书中的第二章“Hello World, the WebWork Way”,Patrick Lightbody and Jason Carreira (Manning Publications, September 2005; ISBN: 1932394532): http://www.manning.com/books/lightbody
---Matrix: http://www.matrix.org.cn