WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的J2EE Web框架。WebWork最新版本是2.2.2,现在的WebWork2.x前身是Rickard Oberg开发的WebWork,但现在WebWork已经被拆分成了XWork1和WebWork2两个项目。实现Interceptor接口的拦截器,代码部分在intercept方法中实现。在intercept方法中,可以直接返回一个Result字符串,这样整个执行直接“短路”,这时Action的execute方法也不会执行(一般很少会这么用)。所以,一般都会在这个方法里调用参数对象invocation的invoke方法,并返回这个方法执行的结果。这样会持续执行后面的拦截器方法以及Action的execute方法等。
基本介绍
WebWork是建立在称为XWork的Command模式框架之上的强大的基于Web的MVC框架。
如下示意图所示:
XWork简洁、灵活功能强大,它是一个标准的Command
模式框架实现,并且完全从web层脱离出来。XWork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的
表达式语言(OGNL – the Object Graph Notation Language),IoC(Inversion of Control依赖倒转控制)容器等。
WebWork2建立在XWork之上,处理HTTP的请求和响应。所有的请求都会被它的前端控制器(ServletDispatcher,最新版本是FilterDispatcher)截获。前端控制器对请求的数据进行包装,初始化上下文数据,根据配置文件查找请求URL对应的Action类,执行Action,将执行结果转发到相应的展现页面。WebWork2支持多视图表示,视图部分可以使用JSP,Velocity,FreeMarker,JasperReports,XML等。
下面我们提到的WebWork将为WebWork2,使用的版本是WebWork2.2.2。
原理
WebWork的网站上提供了一个完整的WebWork架构图。它描述了从客户端的一次请求到最后服务器端响应的整个执行过程。架构图如下:
此架构图一共分为五个部分,其中五个部分分别由五种不同颜色表示。
1.浅灰色方框。分别代表了客户端的一次Http请求,和服务器端运算结束之后的一次响应。
2.浅红色方框。表示一次Action请求所要经过的Servlet filters(Servlet 过滤器)。我们可以看到最后一个filter就是我们前面介绍的WebWork的前端控制器。
3.蓝色方框。这是WebWork框架的核心部分。
(1)一次请求到了WebWork的前端控制器,它首先会根据请求的URL解析出对应的action 名称,然后去咨询ActionMapper这个action是否需要被执行。
(2)如果ActionMapper决定这个action需要被执行,前端控制器就把工作委派给ActionProxy。接着她们会咨询WebWork的配置管理器,并读取在web.
xml文件中定义的配置信息。接下来ActionProxy会创建ActionInvocation对象。
(3)ActionInvocation是Xwork原理的(Command模式)实现部分。它会调用这个Action已定义的拦截器(before方法),Action方法,Result方法。
(4)最后,看上面流程的图的方向,它会再执行拦截器(after方法),再回到Servlet Filter部分,最后结束并传给用户一个结果响应。
4.靛色方框。这是拦截器部分,在上面的拦截器章节我们已经有了详细的介绍。
5.黄色方框。这是我们在开发Web应用时,需要自己开发的程序。其中包括:Action类,页面模板,配置文件xwork.xml。
核心概念
WebWork的三个关键部分
1.Actions。一般一个Action代表一次请求或调用。在WebWork中,一般Action类需要实现Action接口,或者直接继承基础类ActionSupport。这是,它要实现默认的execute方法,并返回一个在配置文件中定义的Result(也就是一个自定义的字符串而已)。当然,Action也可以只是一个POJO(普通Java对象),不用继承任何类也不用实现任何接口。Action是一次请求的控制器,同时也充当数据模型的角色,我们强烈建议不要将业务逻辑放在Action中。
2.Results。它是一个结果页面的定义。它用来指示Action执行之后,如何显示执行的结果。Result Type表示如何以及用哪种视图技术展现结果。通过Result Type,WebWork可以方便的支持多种视图技术;而且这些视图技术可以互相切换,Action部分不需做任何改动。
3.Interceptors。WebWork的拦截器,WebWork截获Action请求,在Action执行之前或之后调用拦截器方法。这样,可以用插拔的方式将功能注入到Action中。WebWork框架的很多功能都是以拦截器的形式提供出来。例如:参数组装,验证,国际化,文件上传等等。
特点介绍
ValueStack 和 EL
关于ValueStack的描述:
1.ValueStack其实就是一个放置Java对象的堆栈而已,唯一特别的是可以使用EL来获得值堆栈中对象属性的数据,并可以为值堆栈的对象属性赋值。
2.EL,全称Express Language,即
表达式语言。不要被语言吓倒,它是简单的对象导航语言。有字符串(例如:方法名)和特殊字符组成(例如用.表示调用对应的属性方法)。通过EL,我们可以存、取对象数据,而且还可以直接访问类的静态数据,调用
静态方法。
3.WebWork的ValueStack底层有第三方开源项目OGNL实现。所以EL也都遵循OGNL的规范。我们在开发中,几乎不需要知道OGNL的细节。
4.WebWork为每一次请求构建一个ValueStack,并将所有相关的
数据对象(例如:Action对象、Model对象等)放到ValueStack中。再将ValueStack暴露给视图页面,这样页面就可以直接访问后台处理生成的数据。
下面我们用一个雇员类为例,使用Junit框架(
单元测试框架)来展示ValueStack的功能。
我们有一个Employee类,它有两个属性:姓名,地址。姓名是一个字符串,地址是一个对象,地址类有国家、城市、街道三个属性。
Interceptor( 拦截器 )
关于拦截器的描述:
1.一个拦截器就是在xwork.xml文件中定义的一个无状态Java类,它至少要实现
XWork的com.opensymphony.xwork.interceptor.Interceptor接口。
2.实现Interceptor接口的拦截器,代码部分在intercept方法中实现。在intercept方法中,可以直接返回一个Result字符串,这样整个执行直接“短路”,这时Action的execute方法也不会执行(一般很少会这么用)。所以,一般都会在这个方法里调用参数对象invocation的invoke方法,并返回这个方法执行的结果。这样会持续执行后面的拦截器方法以及Action的execute方法等。
3.大部分的时候,拦截器直接继承WebWork的
抽象类com.opensymphony.xwork.interceptor.AroundInterceptor就可以了。这时,需要实现它的before和after方法。Before方法会在Action执行之前调用,after方法在Action执行之后调用。
4.拦截器的执行顺序。我们可将多个拦截器放一起组装成一个拦截器栈。这样拦截器会按照栈的顺序由上而下执行before方法,所有before方法执行结束,再执行Action的方法,执行Result的方法,再返回执行结果,最后再从下而上执行拦截器的after方法。
5.拦截器的过滤功能。我们通常会在应用中使用一个通用的定义多个拦截器的拦截器栈。但有些Action方法在调用的时候,不需要要其中的部分拦截器。这时,我们就可以使用拦截器过滤功能。如果拦截器要拥有过滤功能,必须实现抽象类com.opensymphony.xwork.interceptor.MethodFilterInterceptor。这样,拦截器在定义的时候或者在Action引用拦截器栈的时候,我们就可以指定哪些Action方法是需要过滤的,哪些Action是不需要过滤的。
提供的拦截器介绍
1.自动为Action设置Http请求数据的拦截器(Parameters Interceptor)。这个拦截器非常方便实用,但完全自动组装对象数据,很可能会带来安全问题。如果Action不需要设置数据,那么这个Action只要实现com.opensymphony.xwork.interceptor.NoParameters接口即可。如果是Action中部分数据需要自动设置,部分数据不允许设置,这样可以实现接口com.opensymphony.xwork.interceptor.ParameterNameAware,可以在这个接口的acceptableParameterName(String parameterName)方法中,定义我们可以接受哪些方法,如果允许只要让这个方法返回True就可以了。
2.过滤参数功能的拦截器(Parameter Filter Interceptor)。它可以全局阻止非法或不允许Action访问的参数。可以很好的和上面的组装参数的拦截器一起使用。
3.为Action设置静态数据的拦截器(Static Parameters Interceptor)。它可以将Action定义的静态参数,设置到Action中。
4.
数据验证拦截器(Validation Interceptor)。定义之后,会调用验证文件或实现验证接口com.opensymphony.xwork.Validateable的所有验证。
5.验证流程处理拦截器(Workflow Interceptor)。它和上面的拦截器一起使用,处理验证的流程。如果验证通过则继续前进,如果发现有验证错误消息,直接转到Action中定义的输入结果(input)页面。
6.类型转换错误处理拦截器。它首先去取得类型转换的错误消息(主要是由设置Http请求参数的拦截器产生),如果取到错误消息,它会将错误消息传递给实现接口com.opensymphony.xwork.ValidationAware的Action,这样我们可以将这些错误消息暴露到页面中。
7.Action链拦截器(Chaining Interceptor)。它是用来拷贝前一个Action的属性数据到当前Action中。它要求前一个Action必须是chain Result,这样才能进行Action的数据拷贝。
8.防止页面重复提交(或页面重复刷新)拦截器。Token Interceptor和Token Session Interceptor都是防止重复提交的拦截器。不同点是后者在Session存贮了最近一次请求的结果数据。
9.文件上传的拦截器(File Upload Interceptor)。实现文件上传的功能。如果有人曾经手工写过文件上传程序,那一定会惊叹于这个拦截器。我们可以在这个拦截器中设定上传文件的大小和类型限制。记得需要第三方的文件上传库的支持,只要在webwork.properties中配置过,并拷贝相应的jar包就可以了。
10.进度条等待拦截器(Execute and Wait Interceptor)。当Action的执行需要很长时间的时候,我们可以使用这个进度条等待的拦截器。它会将Action放到后台执行,而在
前端显示进度条或等待消息提示的页面。
11.还有一些其它不常用的拦截器,我们可以在WebWork文档中找到,这里就不再做介绍。
使用技巧
限于篇幅,我们无法在本章节给出很多详尽的具体实例。其实,在WebWork的代码包中,有一个非常好的演示项目——
showcase,它用例子演示了WebWork的几乎所有特性。值得初学的朋友反复研究。
1.多视图支持。WebWork框架天生支持多种视图技术,包括:Jsp、FreeMarker、Velocity、Jasper Reports、XSLT,还有其它的视图技术。这将在敏捷项目中特别有用。在我咨询的项目中,就有一个因为技术的原因,视图技术由最先的Jsp改为Velocity,后来又改造为FreeMarker。其中,Action类以及后台的程序没有做任何的改动。如果您需要一个视图展现层技术,我在这会好不犹豫的向您推荐FreeMarker。这也是官方的推荐。
关于视图技术的使用,首先是搭建视图技术运行的环境。然后就是编写页面脚本,最后就是在xwork.xml文件中配置。Xwork配置文件中,Result的type参数,就是用来标示所使用的视图技术。在
showcase项目中,使用到的视图技术有:Jsp、FreeMarker、Velocity、Jasper Reports。
2.Action的
数据验证功能。在WebWork中,可以在三处实现数据验证功能。一、验证文件(例如:ActionClass-validation.xml文件)中定义数据验证规则。二、在Action中实现com.opensymphony.xwork.Validateable接口的validate方法。三、在Action的执行方法中,硬编码实现验证功能。当然,在实现验证时,我们尽可能的用前面两中方法。
关于验证的说明:
(1)、第一种验证需要“validation”拦截器的支持。并可以从任意层次绑定验证文件,可以为一个Action类绑定一个验证文件,也可以为一个具体在xwork.xml文件中的Action定义绑定一个验证文件,可以为Action的一个属性对象绑定一个验证文件,甚至可以为Action的父类绑定验证文件。
(2)、WebWork为验证文件提供了一些标准的验证实现:例如:字段必须填写,整型、E-mail地址等等。我们也可以使用表达式语言实现更复杂的
数据验证。
3.类型转换。前面外面一直提到过,WebWork会自动从请求的字符串参数中组装Action需要的
数据对象。这样,就会存在一个类型转换的问题。如果Action的字段是基本类型或是一个数据对象,WebWork会自动帮我们处理。如果Action的字段是一个集合,或者我们需要特定的类型转换,这时,我们可以在类型转换的
定义文件(ClassName-conversion.properties)中定义转换规则。
4.一个Action的多个执行方法。WebWork的Action是基于Command模式的实现,在WebWork中,除了实现Action接口的execute方法之外,Action还可以定义多个执行方法。这些方法必须要是无方法参数,并且返回返回字符串的方法。这样我们在Url中可以用类似下面的格式访问:actionName!methodName.action,例如user!doAdd.action,调用user Action类的doAdd方法。在最新的WebWork中,Action类甚至可以不实现Action接口。
5.Action链(Action Chaining)。在WebWork中,一次用户请求,可由多个Action共同完成。每个Action可以只实现自己本身的功能单元,这样我们可以根据业务需要为用户的一次请求选择一个或多个Action功能单元来实现。在这样的多个Action之间可以通过chain拦截器共享数据。如果请求由Action x 链到Action y,如果这时y需要获得x的数据,我们就需要为Action y添加chain拦截器。
6.多模块支持解决方案。WebWork 提供了很灵活的多模块解决方案,这样我们可以很好的组织复杂的 Web 应用项目。
(1).可以在 xwork.xml 文件中,用 include 标签包含另外的一个 xwork 配置文件。例如:
(2). xwork.xml 配置文件支持 package。我们可以将一个业务模块的定义方到一个 package , package 支持继承功能,子 package 可以享有父 package 的所有定义。
(3).可以为 package 定义一个命名空间。不同的命名空间可以定义相同的 action 名字。命名空间会用于访问 action 的 URL ,基于这个命名空间,我们可以实现资源权限的
访问控制。
7.doInput 方法。这是我们常用的小技巧,有时候请求的就是一个页面模板,总不能为这个单独写一个 Action 类吧,这时我们就可以用 ActionSupport 的 doInput 方法,直接返回在 Actoion 中定义为“ input ”的 result。
8.prepare方法。如果在Action执行之前,必须要初始化一些数据。我们可以将这些初始化的代码方到prepare方法中。这时,Action类要实现接口com.opensymphony.xwork.Preparable,同时这个Action的定义还需要PrepareInterceptor拦截器的支持。
9.Action的Model Driven。我们大部分的时候用得都是Action的Field Driven,即直接将Action的字段作为数据模型。Model Driven是专门为这个Action指定一个模型对象,这样有什么好处呢?好处是在表达式语言中少了一个对象名的前缀。
10.Quick Start。这是WebWork2.2.2中非常激动人心的特性。它可以象perl或PHP可以快速看到程序运行结果。这样在Web开发时,可以不用编译Java源代码,也不用去做打包和部署,就可以快速看到最新程序的运行结果,提高开发效率。我们可以在WebWork源码解压包的根目录,输入命令:java -jar webwork-2.2.2.jar quickstart:
showcase(需要jdk1.5的支持),以Quick Start模式,运行showcase项目。
安装
如果只是搭建一个WebWork
开发环境,那将非常简单:
1.去下载最新的WebWork2.2.2项目。
3.在Web.xml文件中配置WebWork的前端控制器FilterDispatcher,也就是一个普通的Servlet Filter(过滤器)而已。不过如果是在实际项目中使用,安装过程中还是有一些问题需要注意的:
1.关于前端控制器。
2.关于Action请求URL的后缀。
3.在 Jsp 页面中, WebWork 的
标签库不需要在 web.xml 中定义。
4.在Jsp页面中,默认“altSyntax”是开启的。
5.如果展现层技术使用Freemarker(WebWork官方的推荐,也是我个人的推荐),如果在页面中需要使用标签库,必须在web.xml中配置JspSupportServlet。
6.还有一些其它的定制,比如:编码,标签的模板文件等等,都可以在webwork.properties文件中配置。如果在ClassPath中没有这个文件,WebWork会自动读取WebWork的Jar包里面的default.properties文件。
发展前景
这是很多人非常关心的一个问题。特别是WebWork2.2版本发布之后,官方宣称WebWork框架将要和Struts合并。这让一些WebWork的用户产生了担忧,合并之后,是不是就意味着自己在WebWork这方面技术和经验的积累都已浪费?已使用或即将使用WebWork的项目是不是就意味着更多的风险?
答案是:完全不用担心这些。WebWork和Struts的合并,是各取所长,然后诞生出一个更加高效的Web框架。而这个框架用得就是WebWork的优秀技术和Struts的强大社区。
合并的情况如下:
1.产生一个新的项目Struts Action 2.0 = WebWork2.2 + 一些Struts的功能和特性。
2.WebWork框架将会中止新功能的增加,如果有新的版本发布都会是Bug的修改。
3.代码、框架的开发者、社区都将移到Struts。
4.合并的目标是致力于生产率的提高。
5.Struts不再是一个框架,它是一个社区。
6.Struts社区中主要有两个Web框架。一个是基于Action模型的Struts Action;另一个是基于组件模型的Struts Shale。
WebWork是本人工具箱中最爱的一个J2EE Web框架。本人开发过单纯使用Jsp和JavaServlet的项目;也曾经自己开发过基于MVC的Web框架;在2002年开始使用Struts开发;后来也在项目中分别使用过Tapestry和Spring MVC Web框架;也在当今的AJAX潮流中随波逐流。上面的一些技术也都非常优秀,擅用他们任何一个都会给您带来很多生产效率的提高。但我仍然是偏爱WebWork。WebWork的与众不同,得力于它基于OGNL的强大的数据存、取方式,得力于它那解耦的拦截器功能,得力于它那无侵入的架构设计。正是由于它,才让Web编程变得更加的自然、简单、灵活、高效。