引言
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中
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
com.opensymphony.webwork.dispatcher.ServletDispatcher
//如果使用WebWork自带的标签库则必须载入WebWorkVelocityServlet,
并配置webwork.tld
com.opensymphony.webwork.views.velocity.WebWorkVelocityServlet
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配置文件里应该有这一段:
在xwork.xml配置文件里应该有: 源代码如下: 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配置文件中 webwork-default.xml中已定义的如下: ptor"/> rceptor"/> ceptor"/> tor"/> rInterceptor"/> 框架中定义的Interceptor具体功能如下: ●timer:记录Action执行的时间,并做为日志信息输出; ●logger:在日志信息中输出要执行的Action信息; ●chain:将前一个执行结束的Action属性设置到当前的Action中。它被用在ResultType为“chain”指定结果的Action中,该结果Action对象会从OgnlValueStack中获得前一个Action对应的属性,它实现Action链之间的数据传递; ●static-params:将xwork.xml配置文件里定义的Action参数,设置到对应的Action中。Action参数使用标签,是 ●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栈,使用标签: 4、在webwork.xml中指定Action所要用到的Interceptor(前面申明过的),可以用 如果Action没有用 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全局跳转 定义全局处理结果使用 示例:凡是错误都返回到一个指定的错误页面 global全局异常处理 定义全局异常处理可以集中管理异常,在webwork.xml或其包含的子xml里配置 示例: 当抛出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)。但在实际开发中,一般都使用第二中注册方法。我们的验证类型注册如下: 注册验证类型的配置文件非常简单。它使用标签 创建验证文件 user.password == verifyPassword 6 100 Age must be between ${min} and ${max}, current value is ${user.age}. 说明: 1)、 2)、 3)、验证文件中,字段的数据是通过表达式语言从我们的值堆栈(OgnlValueStack)中取得,一般是Action或Model对象。例如:我们的字段“user.age”,它会通过Action的getUser().getAge()来取得用户输入的年龄,再来根据验证的类型“int”和最大值最小值的参数来判断输入的数据是否能通过验证。 4)、不管验证是否通过, Action都会执行,但如果验证没有通过还是不会调用Action的execute()方法。 开启验证功能 如果Action要使用验证框架的验证功能,它必须在配置文件中指定“validation”,它的定义如下: 我们的验证文件必须以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,我们可以获得类级别或字段级别的验证错误信息,这个错误信息也就是我们验证文件中 webwork实例 参考相应Demo。一般情况一个控制分model块、dao块、business块、control块 model:JavaBean及hibernate表映射文件 dao:分接口和impl实现类,封装hibernate的数据操作 business:管理接口和impl实现类,用于封装dao操作 control:action类,用于业务逻辑处理及调用business管理类进行数据库操作 business管理类是通过一个管理工厂类来获取一个管理类对象下载本文