视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
WebWork手册
2025-09-25 14:16:39 责编:小OO
文档
                               WebWork 使用指南

引言

WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的拉出式MVC模式J2EE Web框架。WebWork已经被拆分成了Xwork1和WebWork2两个项目。

   

Xwork简洁、灵活功能强大,它是一个标准的Command模式实现,并且完全从web层脱离出来。 Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Notation Language),IoC(Inversion of Control倒置控制)容器等。

WebWork2建立在Xwork之上,处理HTTP的响应和请求。WebWork2使用ServletDispatcher将HTTP请求的变成Action(业务层Action类), session(会话)application(应用程序)范围的映射,request请求参数映射。WebWork2支持多视图表示,视图部分可以使用JSP, Velocity, FreeMarker, JasperReports,XML等。在WebWork2.2中添加了对AJAX的支持,这支持是构建在DWR与Dojo这两个框架的基础之上.

用于WebWork辅助开发的一个Eclipse插件: EclipseWork

文件目录

webwork下载一般包含的目录有:

webwork-2.x.jar:WebWrok最新发布的Jar包

webwork-example.war :WebWrok自带的很有代表性的功能演示例

webwork-migration.jar :提供快速将1.x版本移植到2.x版本所用的类文件

docs:WebWrok的使用文档;包括api文档、clover文档、单元测试(Junit)文档等

lib:WebWork在运行或编译时所用到的所有.jar包

src: 源程序目录

xwork运行

当URL发生请求到动作action,将由ServletDispatcher调度,从配置文件xwork.xml里查找与提交动作匹配的Action名字,通过这个名字XWork框架找到对应Action的类;然后 XWork框架会负责去创建这个Action类的对象并调用execute()方法进行用户注册操作。正确执行execute()方法返回String类型数据后,它会请求再派遣到用户所配置指定好的页面。

    当然在action执行之前会先执行配置好的。webwork.xml中

用来配置。其中params是在webwork-default.xml定义好的,可以是"chain"、"model-driven"等等。引用的是

com.opensymphony.xwork.interceptor.ParametersInterceptor。将作用是将request请求的参数值通过表达式语言设置到相应Action的模型里。例如:某jsp里的,它输入的值会由Action类的getUser()和User类的setUserName(“…”)设置到这个User模型里。的使用,使得Action类和Web实现了完全的解耦

开发步骤

描述一个WEB项目使用xwork的开发过程

创建WEB工程

1、新建一个WEB工程将webwork的jar包放到web应用的WEB-INF\\lib目录里

2、将xwork.xml、webwork.properties等webwork配置文件放到WEB-INF\\classes目录

配置文件

Web框架都是通过web.xml配置一个JavaServlet控制器提供统一的请求入口,解析请求

的url,再去调用相应的Action进行业务处理。WebWork也是如此,它是在web.xml文

件里配置一个派遣器ServletDispatcher,ServletDispatcher初始化WebWrok的一些配置

信息,解析XWork的Action配置信息,根据请求去组装和调用执行相应的

(Interceptor)、Action、Action Result(Action执行结果的输出)等。

另外与Struts类似,Webwork也需要配置本身xml。这个文件是xwork.xml,也是设置action及其转向

web.xml

webwork

com.opensymphony.webwork.dispatcher.ServletDispatcher

webwork

*.action

//如果使用WebWork自带的标签库则必须载入WebWorkVelocityServlet,

并配置webwork.tld

velocity

com.opensymphony.webwork.views.velocity.WebWorkVelocityServlet

velocity

*.vm

webwork

/WEB-INF/webwork.tld

xwork.xml 

    

             /main.jsp

        

        

             /index.jsp

        

        

        

    

            

                /login.jsp

            

            

                /error.jsp

            

        

下面是job.xml

    

             login.jsp

        

        

             system/register.jsp

        

    

说明:

1、设置全局跳转

global-results允许定义全局的输出目地,只要继承它所在的package,这些全局定义都是可用的。比如某个package下有多个action配置,那么这些action都可以使用全局的跳转,调用方式与action局部跳转一致。

2、必须包括webwork-default.xml

3、定义一个package,这个包可以继承其它package。继承后则拥有此package中所有action配置

4、namespace命名空间:用于指定一个action调用路径 ,假如此应用项目名为SchdulerCenter,那么要调用此例的注册action(job.xml),页面中提交的路径应为<%=request.getContextPath()%>/job/ register.action。

当成功时返回页面路径为<%=request.getContextPath()%>/job/login.jsp

因为:result目的地没有‘/’出现,表示目标页面的路径与action请求的命名空间路径一致,故将跳转到<%=request.getContextPath()%>/job/ login.jsp

当失败时返回页面路径为<%=request.getContextPath()%>/system/register.jsp

因为:result目的地出现‘/’,表示目标页面的路径是自定义,并非默认与命名空间一致,故将跳转到自定义的目的地<%=request.getContextPath()%>/system/register.jsp

5、通过include节点可将其它配置文件导入至默认配置文件xwork.xml中,此例将job.xml导入。为了业务逻辑更加清晰,建议xwork.xml不设置package,而全部用include导入每个业务块的配置文件。比如关于登陆与注册的action可以创建一个login.xml,login.xml设置好action;有关作业的业务可以创建一个job.xml并设置好action。最后xwork.xml只需要引入这两个xml即可。

6、通过result定义action返回的跳转的名字,跳转的处理模式有:

dispatcher:类似struts的forward,本系统页面间转向,能传递request,session

数据

redirect:浏览器跳转,可转向其它系统页面,无法将request,session数据传送

velocity:将指定的velocity模板作为结果呈现页面

xslt:将指定的xslt作为结果呈现页面、

chain:将处理结果交给另一个Action处理,以实现Action的链式处理

7、通过param设定action跳转相应的资源名称

8、action设定,webwork有name="params"与name="model-driven"两种方式,在webwork-default包都有定义。是在action运行之前执行。model-driven是针对action的Modle驱动模式的实现

9、上面的配置文件在设定方面还可修改为如下:

       //通过interceptors组合params与model-driven,以减少interceptor-ref声明

    

        

            

            

        

    

    

            ...

            //启用组合后的指定,

        

    

模型

通常所指的JavaBean。主要是一些属性及其set/get方法

Action

action操作有两种驱动模式

Property-Driven模式:implements Action或extends ActionSupport

Model-Driven模式:implements Action

注:建议采用Model-Driven模式使得业务逻辑更加清晰

Property-Driven模式

public class InfoAction implements Action{

    /*直接将页面要用的数据封到InfoAction,将InfoAction同时当成Bean*/

    public String company;

    /*重写Action的execute方法,指定返回跳转*/   

    public String execute() throws Exception {

        company = "ultrapower";

        return SUCCESS;        

    }

    public String getCompany() {

        return company;

    }

    public void setCompany(String company) {

        this.company = company;

    }

}

说明:采用此模式,在页面中可以直接使用action属性命名表单控件,如上例中,对于页面有一个文本框,,其中company是Action的属性.在提交页面时company的值自动映射到InfoAction的company属性。此模式建议不采用。

Model-Driven模式

/*此模式将页面要用的数据单独作成Bean类*/

public class Message {

    public String address;

    public String getAddress() {

        return address;

    }

    public void setAddress(String address) {

        this.address = address;

    }

}

然后action

public class MessageAction implements Action {

    /*将页面要用的数据Bean作为属性*/

    public Message message;

    /*重写Action的execute方法,指定返回跳转*/

    public String execute() throws Exception {

        // TODO Auto-generated method stub

        return null;

    }

    public Message getMessage() {

        return message;

    }

    public void setMessage(Message message) {

        this.message = message;

    }

}

说明:采用此模式,在页面中可以直接使用模式属性命名表单控件,如上例中,对于页面有一个文本框,,其中message是Action的属性,即模型类对象Message。address又是模型对象Message的属性,在提交页面时message.address的值自动映射到InfoAction的message属性对象。

采用Model-Driven模式使用webwork标签比较简洁。建议采用

ModelDriven接口

在webwork中提到com.opensymphony.xwork.ModelDriven接口是做什么的呢? 

它是将Object getModel()取得的Model放到ValueStack中。这样在页面就可能使用webwork标签将值输出。 

Property-Driven模式与Model-Driven模式都可以实现这个接口来将Model放入ValueStack

注意: Model-Driven(模型驱动)的Action与com.opensymphony.xwork.ModelDriven接口是二回事。 Model-Driven只是action处理页面的一种方式

Action动态请求

通常情况下提交请求是转到Action的execute方法,webwork允许灵活的配置请求并转到相应的处理方法。如下:

假如LoginAction有execute()方法和view()方法,请求名为login,那么

请求名为login.action时,进入execute()方法。

请求名为login!view.action时,进入view()方法。

ActionContext

由于Xwork与Web无关性,我们的Action不用去依赖于任何Web容器,不用和那些JavaServlet复杂的请求(Request)、响应(Response)关联在一起。对请求(Request)的参数(Param),可以使用框架自动调用一些get()和set()方法设置到对应的Action的字段中。但是,仅仅取得请求参数的值就能完全满足我们的功能要求吗?不,在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息,甚至需要直接对JavaServlet Http的请求(HttpServletRequest)、响应(HttpServletResponse)操作。

ActionContext简介

ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放放的是Action在执行时需要用到的对象,比如:在使用WebWork时,我们的上下文放有请求的参数(Parameter)、会话(Session)、Servlet上下文(ServletContext)、本地化(Locale)信息等。

在每次执行Action之前都会创建新的ActionContext,ActionContext是线程安全的,也就是说在同一个线程里ActionContext里的属性是唯一的,这样我的Action就可以在多线程中使用。

ActionContext获取

通过ActionContext的静态方法:ActionContext.getContext()来取得当前的ActionContext对象,如下代码:

public static ActionContext getContext() {

        ActionContext context = (ActionContext) actionContext.get();

        if (context == null) {

            OgnlValueStack vs = new OgnlValueStack();

            context = new ActionContext(vs.getContext());

            setContext(context);

        }

        return context;

}

其中actionContext对象的创建为:

static ThreadLocal actionContext = new ActionContextThreadLocal();

ActionContextThreadLocal是实现ThreadLocal的一个内部类。ThreadLocal可以命名为“线程局部变量”,它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以地改变自己的副本,而不会和其它线程的副本冲突。这样,我们ActionContext里的属性只会在对应的当前请求线程中可见,从而保证它是线程安全的。

ActionContext运用

接获取HttpServletRequest、HttpServletResponse、HttpSession信息,如下例

例一:获取所有参数中某个参数的值

//取得我们当前的ActionContext对象context

ActionContext context = ActionContext.getContext();

//从context对象里获取我们所有的请求参数,取得的却是一个Map对象

Map params = context.getParameters();

//得到的Map对象有许多参数值,这举例取request请求的“username”参数值

String username = (String) params.get(“username”);

例二:获取HttpSession

Map session = ActionContext.getContext().getSession();

此例取得的session却是Map类型的对象,这是为什么?原来, WebWork框架将与Web相关的很多对象重新进行了包装,比如这里就将HttpSession对象重新包装成了一个Map对象,供我们的Action使用,而不用直接和底层的HttpSession打交道。也正是框架的包装,让我们的Actoion可以完全的和Web层解藕。

ServletActionContext

如果Action需要直接与JavaServlet的HttpSession、HttpServletRequest等一些对象进行操作,则需要利用 ServletActionContext。

ServletActionContext简介

ServletActionContext(com.opensymphony.webwork. ServletActionContext),这个类直接继承了我们上面介绍的ActionContext,它提供了直接与JavaServlet相关对象访问的功能,它可以取得的对象有:

1、javax.servlet.http.HttpServletRequest:HTTPservlet请求对象

2、javax.servlet.http.HttpServletResponse;:HTTPservlet相应对象

3、javax.servlet.ServletContext:Servlet 上下文信息

4、javax.servlet.ServletConfig:Servlet配置对象

5、javax.servlet.jsp.PageContext:Http页面上下文

ServletActionContext除了提供了上面这些对象访问,它当然也继承了它父类ActionContex的很多功能,比如:对OgnlValueStack、Action名字等的访问。

ServletActionContext运用

1、取得HttpServletRequest对象:

HttpServletRequest request = ServletActionContext. getRequest();

2、取得HttpSession对象:

HttpSession session = ServletActionContext. getRequest().getSession();

小结:

由于ServletActionContext继承自ActionContext,因此和ActionContext有着一些重复的功能,在Action中,该如何去抉择呢?遵循的原则是:如果ActionContext能够实现我们的功能,那最好就不要使用ServletActionContext,让我们的Action尽量不要直接去访问JavaServlet的相关对象。在使用ActionContext时有一点要注意:不要在Action的构造函数里使用ActionContext.getContext(),因为这个时候ActionContext里的一些值也许没有设置,这时通过ActionContext取得的值也许是null。

ServletDispatcher原理

ServletDispatcher是默认的处理Web Http请求的调度器,它是一个JavaServlet,是WebWork框架的控制器。所有对Action调用的请求都将通过这个ServletDispatcher调度。它将在web.xml里配置ServletDispatcher时指定,让所有对WebWork 的Action(默认的是.action的后缀)的请求都对应到该调度的JavaServlet中。

ServletDispatcher接受客户端的HTTP请求,将JavaServlet的很多相关对象进行包装,再传XWork框架,由XWork框架去解析xwork.xml配置文件,根据配置文件的信息,创建对应的Action,组装并调用相应的,执行Action,返回执行结果。WebWork使用XWork的核心,主要是由这个ServletDispatcher去实现的。

ServletDispatcher流程

描述ServletDispatcher执行的过程,当提交某个action请求时,依次执行如下:

init

init()方法在服务器启动时调用

1、初始化Velocity引擎

2、检查是否支持配置文件重新载入功能。如果webwork.configuration.xml.reload(见webwork.properties文件)设置为true,每个request请求都将重新装载xwork.xml配置文件。在开发环境使用将会非常方便,但在生产环境必需设置为false。

代码如下:

if ("true".equalsIgnoreCase(Configuration.getString("webwork.configuration.xml.reload"))) {

FileManager.setReloadingConfigs(true);

}

3、设置一些文件上传的信息,比如:上传临时目录,上传的最大字节等。都设置在webwork.properties文件里,如果在classpath中找不到这个属性文件,它会去读取默认的default.properties

service

service()方法,每次客户端的请求都将调用此方法。

1、通过request请求取得action的命名空间(namespace,与xwork.xml配置文件里package

标签的name对应)。

例如:/foo/bar/MyAction.action,取得的命名空间为/foo/bar

在xwork.xml配置文件里应该有这一段:

2、根据servlet请求的Path,解析出要调用该请求的Action的名字(actionName),例如:(../foo/bar/MyAction.action -> MyAction)

在xwork.xml配置文件里应该有:

3、创建Action上下文(extraContext)。前面介绍的ActionContext上下文的对象,就是在这里设置的。它将JavaServlet相关的对象进行包装,放入到extraContext这个Map对象里。

源代码如下:

public static HashMap createContextMap(Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap, HttpServletRequest request, HttpServletResponse response, ServletConfig servletConfig) {

        HashMap extraContext = new HashMap();

        extraContext.put(ActionContext.PARAMETERS, parameterMap);

        extraContext.put(ActionContext.SESSION, sessionMap);

        extraContext.put(ActionContext.APPLICATION, applicationMap);

        extraContext.put(ActionContext.LOCALE, request.getLocale());

        extraContext.put(HTTP_REQUEST, request);

        extraContext.put(HTTP_RESPONSE, response);

        extraContext.put(SERVLET_CONFIG, servletConfig);

        extraContext.put(COMPONENT_MANAGER, request.getAttribute("DefaultComponentManager"));

        extraContext.put("request", requestMap);

        extraContext.put("session", sessionMap);

        extraContext.put("application", applicationMap);

        extraContext.put("parameters", parameterMap);

        AttributeMap attrMap = new AttributeMap(extraContext);

        extraContext.put("attr", attrMap);

        return extraContext;

4、根据前面获得的namespace、actionName、extraContext,创建一个ActonProxy

ActionProxy proxy = ActionProxyFactory.getFactory().

createActionProxy(namespace, actionName, extraContext);

默认的proxy是com.opensymphony.xwork.DefaultActionProxy,在它的构造函数会进行下面的操作:

1)、根据namespace、actionName读取xwork.xml配置文件里这个Action所有配置信息。 

2)、创建ActionInvocation

invocation = ActionProxyFactory.getFactory().createActionInvocation(this, extraContext);

默认的invocation是com.opensymphony.xwork.DefaultActionInvocation,它的构造函数操作有:

a)由com.opensymphony.xwork.ObjectFactory创建我们配置文件描述的Action对象。再将这个Action对象存放入OgnlValueStack中。记得我们前面用户注册的例子吗?当用户提交表达时它会有表达式语言向OgnlValueStack取得Action对象的字段,再把输入框的数据设置到对应的Action字段中,这个Action对象就是在这个时候进栈的。

b)传入extraContext参数,创建与ActionInvocation对应的Action上下文(ActionContext)。记得我们在介绍ActionContext的最后,提出了一个需要注意的地方:不要在Action构造函数中调用ActionContext.getContext()。现在应该能明白,原来是Action对象实例在ActionContext对象实例之前创建的,所有这样取得ActionContext容器对象就有可能会返回null

c)取得这个Action对应的所有(Interceptor),存放入java.util.Iterator对象中。

5、执行proxy的execute()方法,这个方法最核心的语句是:retCode = invocation.invoke();, invocation对象的invoke()方法它遍历并执行这个Action对应的所有,执行Action对应的方法(默认的是execute()),根据Action执行返回的值去调用执行相应的Result(返回结果处理)的方法。

Interceptor()

Interceptor()将Action共用的行为出来,在Action执行前后运行。也就是所说的AOP(Aspect Oriented Programming,面向切面编程),它是分散关注的编程方法,它将通用需求功能从不相关类之中分离出来;同时,能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。

Interceptor将很多功能从我们的Action中出来,大量减少了我们Action的代码,出来的行为具有很好的重用性。XWork、WebWork的许多功能都是有Interceptor实现,可以在配置文件中组装Action用到的Interceptor,它会按照你指定的顺序,在Action执行前后运行。Interceptor在框架中的应用如下图所示:

当你提交对Aciton(默认是.action结尾的Url)的请求时,ServletDispatcher会根据你的请求,去调度并执行相应的Action。在Action执行之前,调用被 Interceptor截取,Interceptor在Action执行前后运行。

Interceptor定义

Request请求参数的在xwork.xml配置文件中标签中设置,这里的 “params”在webwork-default.xml配置文件中有定义。

webwork-default.xml中已定义的如下:

class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>

class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>

class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>

class="com.opensymphony.xwork.interceptor.StaticParametersInterce

ptor"/>

class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>

class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>

class="com.opensymphony.xwork.interceptor.component.ComponentInte

rceptor"/>

class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>

class="com.opensymphony.webwork.interceptor.TokenSessionStoreInter

ceptor"/>

class="com.opensymphony.xwork.validator.ValidationInterceptor"/>

class="com.opensymphony.xwork.interceptor.DefaultWorkflowIntercep

tor"/>

class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>

class="com.opensymphony.webwork.interceptor.WebWorkConversionErro

rInterceptor"/>

框架中定义的Interceptor具体功能如下:

●timer:记录Action执行的时间,并做为日志信息输出;

●logger:在日志信息中输出要执行的Action信息;

●chain:将前一个执行结束的Action属性设置到当前的Action中。它被用在ResultType为“chain”指定结果的Action中,该结果Action对象会从OgnlValueStack中获得前一个Action对应的属性,它实现Action链之间的数据传递;

●static-params:将xwork.xml配置文件里定义的Action参数,设置到对应的Action中。Action参数使用标签,是标签的直接子元素。我们这里定义的Action类必需实现com.opensymphony.xwork.config.entities. Parameterizable接口;

●params:将Request请求的参数设置到相应Action对象的属性中,用户注册例子用到过这个;

●model-driven:如果Action实现ModelDriven接口,它将getModel()取得的模型对象存入OgnlValueStack中;

●component:激活组件功能支持,让注册过的组件在当前Action中可用,即为Action提供IoC(依赖倒转控制)框架的支持;

●token:核对当前Action请求(request)的有效标识,防止重复提交Action请求(request)。

●token-session:功能同上,但是当提交无效的Action请求标识时,它会将请求数据保存到session中。

●validation:实现使用xml配置文件({Action}-validation.xml)对Action属性值进行验证,详细请看后面介绍的验证框架。

●workflow:调用Action类的验证功能,假设Action使用ValidationAware实现验证(ActionSupport提供此功能),如果验证没有通过,workflow会将请求返回到input视图(Action的中定义的)。

●servlet-config:提供Action直接对HttpServletRequest或HttpServletResponse等JavaServlet api的访问,Action要实现相应的接口,例如:ServletRequestAware或ServletResponseAware等。如果必需要提供对JavaServlet api的访问,我们建议使用ServletActionContext,在前面ActionContext章节中有介绍。

●prepare:在Action执行之前调用Action的prepare()方法,这个方法是用来准备Action执行之前要做的工作。它要求我们的Action必需实现com.opensymphony.xwork. Preparable接口

●conversionError:用来处理框架进行类型转化(Type Conversion)时的出错信息。它将存储在ActionContext中的类型转化(Type Conversion)错误信息转化成相应的Action字段的错误信息,保存在堆栈中。根据需要,可以将这些错误信息在视图中显示出来。

Interceptor使用

1、创建一个自己需要的Interceptor类,它必需实现

com.opensymphony.xwork.interceptor.Interceptor接口,如果拦截失败可以在这个类中定义错误的跳转URL

1、在配置文件(xwork..xml)中申明这个Interceptor类,它放在标签中 

           

       

3、创建Interceptor栈,使用标签:,让一组Interceptor可以按次序调用。(可选)

4、在webwork.xml中指定Action所要用到的Interceptor(前面申明过的),可以用

标签。

用于指定某个Action所用到的Interceptor,

如果Action没有用指定Interceptor,它将使用指定的Interceptor。

Interceptor的原理

下面我们来看看Interceptor是如何实现在Action执行前后调用的:

Action和Interceptor在框架中的执行,是由ActionInvocation对象调用的。它是用方法:String invoke() throws Exception;来实现的,它首先会依次调用Action对应的Interceptor,执行完成所有的Interceptor之后,再去调用Action的方法,代码如下:

if (interceptors.hasNext()) {

Interceptor interceptor = (Interceptor) interceptors.next();

resultCode = interceptor.intercept(this);

} else {

      if (proxy.getConfig().getMethodName() == null) {

resultCode = getAction().execute();

} else {

        resultCode = invokeAction(getAction(), proxy.getConfig());

}

}

它会在栈中遍历Interceptor,调用Interceptor的方法:

String intercept(ActionInvocation invocation) throws Exception;。

我们一直都提到,Interceptor是在Action前后执行,可是从上面的代码我们看到的却是执行完所有Interceptor的intercept()方法之后再去调用我们的Action。“在Action前后执行”是如何实现的呢?我们来看看抽象类AroundInterceptor的intercept()实现:

public String intercept(ActionInvocation invocation) throws Exception {

        String result = null;

        before(invocation);

        result = invocation.invoke();

        after(invocation, result);

        return result;

}

原来在intercept()方法又对ActionInvocation的invoke()方法进行递归调用,ActionInvocation循环嵌套在intercept()中,一直到语句result = invocation.invoke();执行结束,即:Action执行完并返回结果result,这时Interceptor对象会按照刚开始执行的逆向顺序依次执行结束。这样before()方法将在Action执行前调用,after()方法在Action执行之后运行。

global全局跳转

定义全局处理结果使用标签,在webwork.xml或其包含的子xml里配置

示例:凡是错误都返回到一个指定的错误页面

/error.jsp

global全局异常处理

定义全局异常处理可以集中管理异常,在webwork.xml或其包含的子xml里配置

示例:

  

 result="exceptionPage"/>   

 

当抛出ArithmeticException异常,上面配置的异常处理就会接手该异常,并把结果交给return为exceptionPage的页面,这个exceptionPage可以配置在全局跳转里

验证框架

WebWork提供了在Action执行之前,对输入数据的验证功能,它使用了其核心XWork的验证框架。提供了如下功能:

1、可配置的验证文件。它的验证文件是一个的XML配置文件,对验证的添加、修改只需更改配置文件,无需编译任何的Class。

2、验证文件和被验证的对象完全解藕。验证对象是普通的JavaBean就可以了(可以是FormBean、域对象等),它们不需实现任何额外的方法或继承额外的类。

3、多种不同的验证方式。因为它验证功能是可以继承的,所以可以用多种不同的方式指定验证文件,比如:通过父类的Action、通过Action、通过Action的方法、通过Action所使用的对象,等等。

4、强大的表达式验证。它使用了OGNL的表达式语言,提供强大的表达式验证功能。

5、同时支持服务器端和客户端验证。

用户注册验证功能示例

下面来看看如何为用户注册添加验证功能:

配置验证类型文件

WebWork为不同的验证要求提供不同的验证类型。一个验证类型,一般是有一个类来提供。这个类必须实现接口:com.opensymphony.xwork.validator.Validator,但我们在写自己的验证类型时,无需直接实现Validator接口,它有抽象类可供直接使用如ValidatorSupport、FieldValidatorSupport等。

验证类型在使用之前,必须要在ValidatorFactory

(com.opensymphony.xwork.validator. ValidatorFactory)中注册。可以有二种方法实现验证类型的注册。一、写程序代码进行注册,它使用ValidatorFactory类的静态方法:registerValidator(String name, String className)。二、使用配置文件validators.xml进行注册,要求把文件validators.xml放到ClassPath的跟目录中(/WEB-INF/classes)。但在实际开发中,一般都使用第二中注册方法。我们的验证类型注册如下:

    

    

    

    

    

    

    

    

    

    

    

注册验证类型的配置文件非常简单。它使用标签提供名-值对的形式注册。这样我们的验证文件就可以直接引用它的名字。

创建验证文件

    

        

            You must enter a value for username.

        

    

    

        

            You must enter a value for password.

        

        

            

user.password == verifyPassword

            Passwords don't match.

        

    

    

        

            You must enter a valid email.

        

    

    

        

            6

            100

            

Age must be between ${min} and ${max}, current value is ${user.age}.   

        

    

说明:

1)、标签代表一个字段,它的属性“name”和页面输入框的“name”属性必需完全一致,其实它也就是我们的表达式语言。

2)、标签定义我们的验证规则,type属性的值就是就是我们前面定义的验证类型。

3)、验证文件中,字段的数据是通过表达式语言从我们的值堆栈(OgnlValueStack)中取得,一般是Action或Model对象。例如:我们的字段“user.age”,它会通过Action的getUser().getAge()来取得用户输入的年龄,再来根据验证的类型“int”和最大值最小值的参数来判断输入的数据是否能通过验证。

4)、不管验证是否通过, Action都会执行,但如果验证没有通过还是不会调用Action的execute()方法。

开启验证功能

如果Action要使用验证框架的验证功能,它必须在配置文件中指定“validation”,它的定义如下:

class="com.opensymphony.xwork.validator.ValidationInterceptor"/>

我们的验证文件必须以ActionName-validation.xml格式命名,它必须被放置到与这个Action相同的包中。你也可以为这个Action通过别名的方式指定验证文件,它的命名格式为:ActionName-aliasname-validation.xml。“ActionName ”是我们Action的类名;“aliasname”是我们在配置文件(xwork.xml)中定义这个Action所用到的名称。这样,同一个Action类,在配置文件中的不同定义就可以对应不同的验证文件。验证框架也会根据Action的继承结构去查找Action的父类验证文件,如果找到它会去执行这个父类的验证。

验证错误信息

如果用户输入的数据验证没有通过,我们需重新返回输入页面,并给出错误信息提示。栈“validationWorkflowStack”为我们实现了这个功能。它首先验证用户输入的数据,如果验证没有通过将不执行我们Action的execute()方法,而是将请求重新返回到输入页面。

我们的xwork.xml配置文件如下:

            

                /register-result.jsp

            

            

                /registerSupport.jsp

            

            

        

通过接口ValidationAware,我们可以获得类级别或字段级别的验证错误信息,这个错误信息也就是我们验证文件中标签里的数据。ActionSupport类已实现了此接口,这样在应用中我们的Action只要继承ActionSupport类就可以了。

webwork实例

参考相应Demo。一般情况一个控制分model块、dao块、business块、control块

model:JavaBean及hibernate表映射文件

dao:分接口和impl实现类,封装hibernate的数据操作

business:管理接口和impl实现类,用于封装dao操作

control:action类,用于业务逻辑处理及调用business管理类进行数据库操作

business管理类是通过一个管理工厂类来获取一个管理类对象下载本文

显示全文
专题