webwork教程.docx
《webwork教程.docx》由会员分享,可在线阅读,更多相关《webwork教程.docx(66页珍藏版)》请在冰豆网上搜索。
webwork教程
WebWork教程-0.90版
作者:
moxie(安子)
发布记录:
2004-6-29:
WebWork教程0.90版
说明:
本次发布的是初稿部分,除了章节:
“实战G-Roller-WW”、“WebWork与其它开源项目的集成”,其余章节全部完成。
目录
WebWork教程-0.90版1
WebWork介绍3
WebWork安装-HelloWorld3
WebWork安装3
HelloWorld4
Action(动作)6
Action介绍6
用户注册例子6
Field-DrivenActionvs.Model-DrivenAction10
ActionContext(Action上下文)12
ActionContext介绍12
ServletActionContext13
ServletDispatcher原理14
Action的单元测试17
ResultType18
表达式与言EL和OGNL22
OGNL介绍22
值堆栈-OgnlValueStack22
Interceptor(拦截器)框架28
Interceptor的原理31
验证框架32
为用户注册添加验证功能32
XWork配置详述37
xwork.xml文件的标签元素37
实战G-Roller-WW41
G-Roller-WW介绍41
JSTL与WebWork的整合41
中文解决方案41
WebWork与其它开源项目的集成41
Spring41
Hibernate41
Xml-RPC41
总结42
附录42
我钟爱的Opensympnony42
从技术的角度Struts1.1与WebWork2的比较44
WebWork的项目资源46
参考资料46
WebWork介绍
WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的拉出式MVC模式J2EEWeb框架。
WebWork目前最新版本是2.1,现在的WebWork2.x前身是RickardOberg开发的WebWork,但现在WebWork已经被拆分成了Xwork1和WebWork2两个项目,如下示意图所示:
Web
Non-web
Xwork简洁、灵活功能强大,它是一个标准的Command模式实现,并且完全从web层脱离出来。
Xwork提供了很多核心功能:
前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL–theObjectGraphNotationLanguage),IoC(InversionofControl倒置控制)容器等。
WebWork2建立在Xwork之上,处理HTTP的响应和请求。
WebWork2使用ServletDispatcher将HTTP请求的变成Action(业务层Action类),session(会话)application(应用程序)范围的映射,request请求参数映射。
WebWork2支持多视图表示,视图部分可以使用JSP,Velocity,FreeMarker,JasperReports,XML等。
下面我们提到的WebWork将为WebWork2,使用的版本是2.1。
WebWork安装-HelloWorld
WebWork安装
当然,在具体开发使用介绍之前,搭建好运行环境是必备的。
首先从
webwork-2.x.jar当然就是WebWrok最新发布的Jar包
webwork-example.war是WebWrok自带的很有代表性的功能演示例子,掌握它是提高你的WebWork技术水平的捷径
webwork-migration.jar提供快速将1.x版本移植到2.x版本所用的类文件
docs目录WebWrok的使用文档,包括api文档、clover文档、单元测试(Junit)文档等
lib目录WebWork在运行或编译时所用到的所有.jar包
src目录源程序目录
2、WebWork是J2EEWeb框架,当然要运行在Web容器中,我用的是稳定的Tomcat4.1,关于tomcat的安装和部署请自己搞定。
3、用WebWork当然要将它的运行时用到的Jar包放到Web容器可以找到的ClassPath中,将步骤1介绍的webwork-2.x.jar放到你部署目录下WEB-INF\lib目录里,同时将WebWrok解压目录lib\core下的所有.jar文件也拷贝到WEB-INF\lib目录,这些是运行WebWork必需要用到的jar包。
4、了解Web框架的朋友都知道,一般Web框架都是通过一个JavaServlet控制器提供统一的请求入口,解析请求的url,再去调用相应的Action进行业务处理。
WebWork也不例外,它要求你在web.xml文件里配置一个派遣器ServletDispatcher,它初始化WebWrok的一些配置信息,解析XWork的Action配置信息,根据请求去组装和调用执行相应的拦截器(Interceptor)、Action、ActionResult(Action执行结果的输出)等,具体配置如下:
……
webwork
com.opensymphony.webwork.dispatcher.ServletDispatcher
……
webwork
*.action
……
这样,.action结尾的所有url请求将直接有ServletDispatcher去调度。
下面我们写一个经典的HelloWorld,跑一个简单实例来验证你运行环境是否可用,并感受一下简单、功能强大的WebWork的开发。
注意:
如果使用WebWork自带的标签库,除了配置相应的标签库以外,还须将com.opensymphony.webwork.views.velocity.WebWorkVelocityServlet配置到web.xml,具体可以参考webwork-example里面的配置。
HelloWorld
首先看下面这个程序HelloWorldAction.java:
packagehelloWorld
importcom.opensymphony.xwork.Action;
publicclassHelloWorldActionimplementsAction{
Stringgreeting;
publicStringgetGreeting(){
returngreeting;
}
publicStringexecute()throwsException{
greeting="HelloWorld!
";
returnSUCCESS;
}
}
HelloWorldAction是一个普通的Java类,它实现了Action这个接口。
Action是一个非常简单的接口,只有一个方法:
publicStringexecute()throwsException;,Action类介绍见下一节。
HelloWorldAction有一个String类型字段greeting,在execute()方法中,greeting被赋值“HelloWorld!
”,并返回String型常量SUCCESS,SUCCESS的定义详见Action接口,这个常量代表了execute()方法执行成功,将返回成功页面。
返回的页面greetings.jsp代码如下:
<%@taglibprefix="ww"uri="webwork"%>
FirstWebWorkExamplepropertyvalue="greeting"/>
greetings.jsp很简单的jsp页面,它使用了WebWork自带的标签库。
它的作用是输出变量“greeting”的值。
这个propertyvalue="greeting"/>语句,相当于调用相应Action(HelloWorldAction)的getGreeting()方法,取得变量“greeting”的值。
我们的HelloWorld代码就这么多,完了。
可是,HelloWorldAction怎么去调用、执行?
执行成功它又怎么知道返回到greetings.jsp?
XWork的配置文件xwork.xml会负责将要执行的Action和展现的视图连接起来,见xwork.xml的如下片断:
/greetings.jsp
我们先看action标签:
name=”hello”,表示我们调用这个Action的标识是hello,这样我们可以通过下面的url访问这个Action:
…/hello.action,
例如:
http:
//localhost:
8080/webwork/hello.action;class="helloWorld.HelloWorldAction"很好理解,这是真正调用执行的类。
我们在看看result标签:
name="success",记得前面HelloWorldAction返回的字符常量SUCCESS吗?
它的值其实就是“success”,它表示Action执行成功返回success就转向这个结果;type="dispatcher"表示执行完Action,转向结果页面的方式;param参数指定了结果页面的位置:
/greetings.jsp。
代码写完,剩下的当然是编译、部署。
启动tomcat服务器之后我们就可以执行了:
在浏览器里输入你的地址:
http:
//localhost:
8080/webwork/hello.action
你将会看到如下结果:
Action(动作)
Action介绍
Action在MVC模式中担任控制部分的角色,在WebWork中使用的最多。
每个请求的动作都对应于一个相应的Action,一个Action是一个独立的工作单元和控制命令,它必需要实现XWork里的Action接口,实现Action接口的execute()方法。
Action接口的代码如下:
packagecom.opensymphony.xwork;
importjava.io.Serializable;
publicinterfaceActionextendsSerializable{
publicstaticfinalStringSUCCESS="success";
publicstaticfinalStringNONE="none";
publicstaticfinalStringERROR="error";
publicstaticfinalStringINPUT="input";
publicstaticfinalStringLOGIN="login";
publicStringexecute()throwsException;
}
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:
packageregister;
publicclassUser{
privateStringusername;
privateStringpassword;
privateStringemail;
privateintage;
publicStringgetUsername(){
returnusername;
}
publicvoidsetUsername(Stringusername){
this.username=username;
}
……
publicintgetAge(){
returnage;
}
publicintsetAge(intage){
this.age=age;
}
publicStringtoString(){
return"username="+username
+";password="+password
+";email="+email
+";age="+age;
}
}
模型User是一个普通的JavaBean,它包含了用户注册的字段信息,并对每个字段提供相应的set和get方法。
下面我们来看看进行用户注册动作的RegisterAction.java:
packageexample.register;
importcom.opensymphony.xwork.Action;
/**
*@authormoxie-qac
*achqian@
*/
publicclassRegisterActionimplementsAction{
privateUseruser=newUser();
publicUsergetUser(){
returnthis.user;
}
publicStringexecute(){
System.out.println("Startexecute。
。
。
。
。
。
。
。
。
。
。
。
。
");
System.out.println("User="+user);
//在这里调用用户注册的业务逻辑,比如:
将注册信息存储到数据库
returnSUCCESS;
}
}
这个Action是不是特清爽?
用户注册就这么几行代码搞定,当然,我们提倡在Action里最好不要实现业务代码,Action的主要功能是提供从请求中取得参数的值,转化成相应的模型,再将模型传递给执行业务操作的对象,比如:
将注册的用户信息存储到数据库中,由业务对象执行业务操作,再返回执行的结果。
为了简化我们省去了注册的业务逻辑执行步骤。
再看看我们注册信息输入的页面:
register.jsp
RegisterExample
Username:
Password:
Email:
Age:
|
register.jsp页面其实只是一个普通的HTML页面,它提供了一个表单,用来接受用户输入的注册信息,它唯一特殊的部分就是input输入框定义的name部分,例如:
用户姓名用的是“user.username”。
这种命名方式代表什么含义?
它是必需的吗?
后面我们将会给出答案。
RegisterAction正确执行完成之后,会将执行的结果返回到register-result.jsp页面,由它来显示用户在前面页面输入的注册信息。
register-result.jsp代码如下:
<%@taglibprefix="ww"uri="webwork"%>
Registerresult
Congratulation,yourregistersuccess!
Username:
propertyvalue="user.username"/>
Password:
propertyvalue="user.password"/>
Email:
propertyvalue="user.email"/>
Age:
propertyvalue="user.age"/>
|
这个Jsp页面使用了WebWork的标签库property/>,记得HelloWorld里的greetings.jsp吗?
它也使用了这个标签库。
我们看这个:
propertyvalue="user.username"/>
它是一个普通的使用标签库语句,查看这个标签库的源程序,见包
com.opensymphony.webwork.views.jsp里的PropertyTag.java文件,你会发现这个类会根据value后面赋予的表达式值,去OgnlValueStack里查找这个表达式值所对应的操作。
执行这个语句OgnlValueStack会根据value的值(一个表达式)“user.username”去分别调用RegisterAction类的getUser()和User类的getUsername()方法,即:
getUser().getUsername(),取得的数据就是前面注册页面输入的用户名。
我们把“user.username”这样的语句叫做表达式语言(ExpressionLanguage,简称为EL)。
它由XWork框架提供,XWork表达式语言的核心是OGNL(ObjectGraphNotationLanguage),OGNL是一种功能强大,技术成熟,应用广泛的表达式语言,将在下面的章节有详细介绍。
我们在回到前面介绍的register.jsp,Input输入框
里用的“user.username”,现在我们可以明白,它不是随意设置的,它是一个表达式语言,有着特殊的功能。
看到这里,不知道你心中是否有一个疑问:
我们的RegisterAction是如何取得用户注册页面输入的数据呢?
如果你做过Web开发,你一定会想到RegisterAction里必需有一些从客户端请求中获取参数的语句,例如:
类似:
Stringusername=request.getParameter(“user.username”)的语句(request是HttpServletRequest的对象),去从request请求里面获取用户输入的参数值。
可是我们这个Action里面只有User对象简单的get方法,并没有其它的代码。
Xwork框架的Action是如何去实现了与Web无关?
request请求的参数是怎么传递到我们Action的模型User中呢?
在回答答案之前,我们先看一看Xwork的配置文件xwork.xml:
/register-result.jsp
看了前面的介绍,这段配置文件应该不难理解。
用户通过注册页面register.jsp输入自己的注册信息,提交表单到动作register.action,它将有ServletDispatcher调度,从配置文件xwork.xml里查找与“register”匹配的Action名字,即上面配置的Action。
通过这个名字XWork框架找到这个Action的类:
example.register.RegisterAction,XWork框架会负责去创建这个Action类的对象并调用execute()方法进行用户注册操作。
正确执行execute()方法返回String类型数据“success”之后,它会请求再派遣到r