HelloWorld
首先看下面这个程序HelloWorldAction.java:
代码
package helloWorld import com.opensymphony.xwork.Action; public class HelloWorldAction implements Action{ String greeting; public String getGreeting() { return greeting; } public String execute() throws Exception { greeting = "Hello World!"; return SUCCESS; } }
HelloWorldAction是一个普通的Java类,它实现了Action这个接口。Action是一个非常简单的接口,只有一个方法:public String execute() throws Exception; ,Action类介绍见下一节。HelloWorldAction有一个String类型字段greeting,在execute()方法中,greeting被赋值“Hello World!”,并返回String型常量SUCCESS,SUCCESS的定义详见Action接口,这个常量代表了execute()方法执行成功,将返回成功页面。 返回的页面greetings.jsp代码如下:
代码
<%@ taglib prefix="ww" uri="webwork" %>First WebWork Example
greetings.jsp很简单的jsp页面,它使用了WebWork自带的标签库。它的作用是输出变量“greeting”的值。这个 语句,相当于调用相应Action(HelloWorldAction)的getGreeting()方法,取得变量“greeting”的值。 我们的HelloWorld代码就这么多,完了。可是,HelloWorldAction怎么去调用、执行?执行成功它又怎么知道返回到greetings.jsp?XWork的配置文件xwork.xml会负责将要执行的Action和展现的视图连接起来,见xwork.xml的如下片断:
我们先看action标签:name=”hello”,表示我们调用这个Action的标识是hello,这样我们可以通过下面的url访问这个Action:…/hello.action, 例如:;class=" helloWorld .HelloWorldAction"很好理解,这是真正调用执行的类。我们在看看result标签:name="success",记得前面HelloWorldAction返回的字符常量SUCCESS吗?它的值其实就是“success”,它表示Action执行成功返回success就转向这个结果;type="dispatcher"表示执行完Action,转向结果页面的方式;param参数指定了结果页面的位置:/greetings.jsp。 代码写完,剩下的当然是编译、部署。启动tomcat服务器之后我们就可以执行了: 在浏览器里输入你的地址: 你将会看到结果
Action(动作) Action介绍 Action在MVC模式中担任控制部分的角色,在WebWork中使用的最多。每个请求的动作都对应于一个相应的Action,一个Action是一个独立的工作单元和控制命令,它必需要实现XWork里的Action接口,实现Action接口的execute()方法。Action接口的代码如下:
代码
package com.opensymphony.xwork; import java.io.Serializable; public interface Action extends Serializable { public static final String SUCCESS = "success"; public static final String NONE = "none"; public static final String ERROR = "error"; public static final String INPUT = "input"; public static final String LOGIN = "login"; public String execute() throws Exception; }
excute()方法是Action类里最重要的部分,它执行返回String类型的值,在Action中返回的值一般使用它上面定义的标准静态字符常量。例如:前面的HelloWorldAction返回的就是SUCCESS字符常量,真正的值当然就是“success”,它与xwork配置文件里result标签name的值是相对应的。它用来决定execute()方法执行完成之后,调用哪一种返回结果。字符常量的含义如下: SUCCESS:Action正确的执行完成,返回相应的视图; NONE:表示Action正确的执行完成,但并不返回任何视图; ERROR:表示Action执行失败,返回到错误处理视图; INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图; LOGIN:Action因为用户没有登陆的原因没有正确执行,将返回该登陆视图,要求用户进行登陆验证。 用户注册例子 下面我们将以一个用户注册的例子详细介绍Action的原理: 功能描述:一个用户注册页面register.jsp,用户可以在这个页面里输入用户注册的基本信息(例如:姓名、密码、Email等),输入完成提交表单,执行用户注册的Action,执行成功返回成功提示的页面(register-result.jsp)并将注册的信息输出。 模型:User.java 控制:RegisterAction.java 视图:register.jsp、register-result.jsp 配置:xwork.xml User.java:
代码
package register; public class User { private String username; private String password; private String email; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } …… public int getAge() { return age; } public int setAge(int age) { this.age = age; } public String toString() { return "username=" + username + ";password=" + password + ";email=" + email + ";age=" + age; } }
模型User是一个普通的JavaBean,它包含了用户注册的字段信息,并对每个字段提供相应的set和get方法。下面我们来看看进行用户注册动作的RegisterAction.java:
代码
package example.register; import com.opensymphony.xwork.Action; /** * @author moxie-qac * achqian@yahoo.com.cn */ public class RegisterAction implements Action { private User user= new User(); public User getUser() { return this.user; } public String execute() { System.out.println("Start execute 。。。。。。。。。。。。。"); System.out.println("User="+user); //在这里调用用户注册的业务逻辑,比如:将注册信息存储到数据库 return SUCCESS; } }
这个Action是不是特清爽?用户注册就这么几行代码搞定,当然,我们提倡在Action里最好不要实现业务代码,Action的主要功能是提供从请求中取得参数的值,转化成相应的模型,再将模型传递给执行业务操作的对象,比如:将注册的用户信息存储到数据库中,由业务对象执行业务操作,再返回执行的结果。为了简化我们省去了注册的业务逻辑执行步骤。 再看看我们注册信息输入的页面:register.jsp
register.jsp页面其实只是一个普通的HTML页面,它提供了一个表单,用来接受用户输入的注册信息,它唯一特殊的部分就是input输入框定义的name部分,例如:用户姓名用的是“user. username”。这种命名方式代表什么含义?它是必需的吗?后面我们将会给出答案。 RegisterAction正确执行完成之后,会将执行的结果返回到register-result.jsp页面,由它来显示用户在前面页面输入的注册信息。register-result.jsp代码如下:
代码
<%@ taglib prefix="ww" uri="webwork" %>Register result Congratulation,your register success! Username: Password: Email: Age:
这个Jsp页面使用了WebWork的标签库 ,记得HelloWorld里的greetings.jsp吗?它也使用了这个标签库。我们看这个: 它是一个普通的使用标签库语句,查看这个标签库的源程序,见包com.opensymphony.webwork.views.jsp里的PropertyTag.java文件,你会发现这个类会根据value后面赋予的表达式值,去OgnlValueStack里查找这个表达式值所对应的操作。执行这个语句OgnlValueStack会根据value的值(一个表达式)“user.username”去分别调用RegisterAction类的getUser()和User类的getUsername()方法,即:getUser().getUsername(),取得的数据就是前面注册页面输入的用户名。 我们把“user.username”这样的语句叫做表达式语言(Expression Language,简称为EL)。它由XWork框架提供,XWork表达式语言的核心是OGNL(Object Graph Notation Language),OGNL是一种功能强大,技术成熟,应用广泛的表达式语言,将在下面的章节有详细介绍。 我们在回到前面介绍的register.jsp,Input输入框 里用的“user.username”,现在我们可以明白,它不是随意设置的,它是一个表达式语言,有着特殊的功能。看到这里,不知道你心中是否有一个疑问:我们的RegisterAction是如何取得用户注册页面输入的数据呢?如果你做过Web开发,你一定会想到RegisterAction里必需有一些从客户端请求中获取参数的语句,例如: 类似:String username = request.getParameter(“user. username”)的语句(request是HttpServletRequest的对象),去从request请求里面获取用户输入的参数值。可是我们这个Action里面只有User对象简单的get方法,并没有其它的代码。Xwork框架的Action是如何去实现了与Web无关?request请求的参数是怎么传递到我们Action的模型User中呢? 在回答答案之前,我们先看一看Xwork的配置文件xwork.xml:
看了前面的介绍,这段配置文件应该不难理解。用户通过注册页面register.jsp输入自己的注册信息,提交表单到动作register.action,它将有ServletDispatcher调度,从配置文件xwork.xml里查找与“register”匹配的Action名字,即上面配置的Action。通过这个名字XWork框架找到这个Action的类:example.register.RegisterAction,XWork框架会负责去创建这个Action类的对象并调用execute()方法进行用户注册操作。正确执行execute()方法返回String类型数据“success”之后,它会请求再派遣到register-result.jsp页面。 在这段配置文件里,你一定注意到了它特殊的一句: ,interceptor-ref标签设置这个Action用到的拦截器(Interceptor),“params”引用的是配置文件中的 ,这个拦截器将在RegisterAction的execute()方法执行之前调用,作用是将request请求的参数值通过表达式语言设置到相应RegisterAction的模型里。例如:register.jsp里的 ,它输入的值会由RegisterAction类的getUser()和User类的setUserName(“…”)设置到这个User模型里。假设你在注册页面输入用户名“moxie”,提交表单ParametersInterceptor就会下面的操作:首先从请求中取得参数的名字和名字对应的值,分别为:“user.username”和“moxie”,根据这个名字,从OgnlValueStack中取得堆栈最上面的getUser().setUsername(“moxie”)操作,即取得RegisterAction对象的User模型,并设置username属性的值为“moxie”。 原来,我们的Action是通过XWork的拦截器ParametersInterceptor从提交的表单中取得请求的参数和值,再通过OgnlValueStack来执行表达式,调用Action和模型里相应的ge或set方法,将从请求中取得的值设置到模型中去。register.jsp中Input输入框的name="user.username"是必需要遵守OGNL的命名规则。也正是很多拦截器的使用,使得我们的Action类和Web实现了完全的解耦,让我们的Action能如此的简单、优雅,拦截器的原理后面章节我们也将会有详细的介绍。 罗索了这么多,你一定是精通了这个用户注册的例子了吧!呵呵!
==================================================================================
WebWork实例
webwork com.opensymphony.webwork.dispatcher.ServletDispatcher webwork *.action webwork /WEB-INF/lib/webwork-2.1.7.jar
hello.jsp index.jsp
webwork.tag.altSyntax = true
package hbu.cmc.webwork.action;
import com.opensymphony.xwork.ActionSupport;
public class HelloWorld extends ActionSupport { private String name = null; private String message= null; public String execute() throws Exception { if(name==null||"".equals(name)) { addFieldError("name","name is null!"); return INPUT; } message = "hello,"+name; return SUCCESS; } public String getMessage() { return message; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setMessage(String message) { this.message = message; } }
index.jsp
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ taglib prefix="ww" uri="webwork" %>
Insert title here
hello.jsp
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ taglib prefix="ww" uri="webwork" %>
Insert title here //输出message的内容
发现webwork要比stucts好用一些,第一webwork 进一步隐去了一些细节。比如没有structs的formbean了,这一点很好。
webwork也就三部分组成,第一部分当然就是JSP,JSP标签。第二部分便是webwork的servlet他是接收客户端的请求,并他解析出相应的action名,通过xwork转发到处理求的后台处理程序上。
然后就是后台处理后通过返回字段来判断要跳转的页面。
整个流程大致如此。