如何移植BEA Webflow 应用到Struts下?
【IT168 专稿】BEA提出了Webflow/Pipeline框架来替代Struts作为网络应用软件的开发框架。同Struts一样,Webflow也是基于MVC模式的框架之一,并且提供的功能也与其它基于MVC模式的框架几近相同。但是因为Webflow使用了BEA 和 WebLogic的私有库,所以以Webflow框架开发的应用程序只能在WebLogic应用服务器上运行,这就限制了其功能的开发。目前,许多IT组织已经意识了这一点,都渴望能够将在Webflow框架开发的应用软件移植到诸如Struts之类的开源框架中去,以此来提高应用程序的灵活性和可维护性。
本文就是专为那些计划或者正在移植Web应用软件的开发人员和系统构架人员所写,通过本文你可以了解到如何通过使用合理的软件开发工具(本文中提到了RAD)将基于Webflow框架开发的应用软件移植到Struts框架。为了更好的理解本文您需要熟悉JAVA编程, Struts框架以及RAD测试环境。
通过阅读本文,您将学会如何剖析WebLogic框架下开发的简单Web应用程序,并且逐渐掌握如何高效的将不同的组件移植到Struts。
剖析Webflow应用程序
正如Brian Pontarelli和 Grant Zemont所说的"Go with the Flow"(与流程搭配)(Java世界,2003.2),Webflow全部是由节点和抽象组件组成(这些抽象组件也就是Web应用程序中的对象)。节点通过事件连接起来:原始的JSP文件--〉输入处理器--〉目的文件。其中,每一个“--〉”都代表着Webflow系统处理的一次事件,那么把所有的节点连接起来就成为了一个Web应用程序的逻辑流程。因此,Webflow就是由这样的节点的组成的序列。
下面是一个BEA Webflow/Pipeline构架的典型Web应用程序,它有以下四个组件:
1.BEA为视图提供的标签库
2.管道组件和管道序列
3.输入处理器
4.Webflow应用程序接口和属性文件
Webflow 应用程序的核心是一个叫做Webflow.properties 的属性文件。它用于控制Web页面的显示以及控制与这些页面相关的商业逻辑的执行。该文件中记录了每一个JSP页面的一部分细节。
一般地,Webflow.properties文件记录每次转变的语法如下:
<origin>.[<event>][(<eventName>)]=<target>
下表描述了语句中各组成元素的所有有效值:

例如,login.jsp.button(createUser)= nextpage.jsp,这是webflow.properties 文件中典型的登陆页面的记录。目前的状态是login.jsp,事件是一个名为createUser的按钮,结果状态是nextpage.jsp。
注意:这里并没有用到输入控制器和管道组件。在这个登陆页面里,表单标签通过WebFlowJSPHelper编程接口于下一个页面建立了URL。这个URL包含了页面的名称以及存储在webflow.properties文件当中与当前状态相匹配的事件。
移植一个简单的Webflow 应用到Structs下
在这篇文章中,我将通过一个简单的 ComputeDay 应用来讲解一下如何移植一个Webflow 应用到Struts下(代码可以在资源下载:http://www.javaworld.com/javaworld/jw-03-2007/jw-03-migrate.html#resources)。ComputeDay应用由一个简单的Web页组成,该页接受用户年、月、日的输入并通过代码处理得到输入的日期是一个星期中的哪一天。如果输入有效,计算得到的值将显示在另一个输出页。否则,在原输入页面显示错误信息。
The webflow.properties file for such a simple application looks like this one:
类似于这样的简单应用的配置文件webflow.properties可能如下所示:
# 调用输入处理 index.jsp.button(submit)= ComputeDay.inputprocessor # 为输入处理指定类的全名 ComputeDay.inputprocessor=com.beasys.commerce.ebusiness. customer.webflow.ComputeDay # 执行成功的结果状态 ComputeDay.inputprocessor.success = Output.jsp #执行失败的结果状态 ComputeDay.inputprocessor.exception(ProcessingException)=index.jsp
注意:由index页到动作句柄,再到输出页还是返回到index页的事件链取决于动作句柄的执行是否成功。
移植Webflow 组件到 Struts下
这一节描述了如何利用RAD,将一个简单的Webflow应用(ComputeDay)的独立的组件一步一步地移植到相应的Struts组件下。为了简化移植,我根据应用的视图、模型和控制器三个层面提供了移植步骤。
步骤1:创建一个空的Struts工程(使用RAD,创建空的Struts工程)
1.在【菜单】工具栏,点击【新建】,选择【动态WEB工程】
2.指定该工程的名称为:ComputeDay
3.单击【下一步】
4.在【定制属性】页,确保勾选了Struts复选框
5.点击【完成】
6.在RAD中建立的Struts工程应该与图1相似

步骤2:确定应用程序组件
确定应用程序组件是一个简单但重要的移植步骤.这里,你必须先确定你的 Webflow 应用包结构。一个典型的Webflow应用包结构如下:
•JAVA代码:包含模型和控制器组件。
•Web组件:包含JSP,HTML,CSS,标签库,WebLogic.xml, Web.xml和图片等等。
•属性:包含webflow.properties和应用程序指定的属性文件。
•JAR包:JAVA归档文件,可能是特定的WebLogic库文件或者应用程序相关的库文件 。
注意,以上的包结构仅仅作为一个指导建议,对于不同的组织通常会有细微的区别。你应该完整地分析要移植的应用程序来确定以上提到的组件。
步骤3:导入应用程序组件
接下来,我们将步骤2中确定的Webflow 组件导入到我们在步骤一中建立的Struts工程结构中。RAD提供了拖放功能,因此你可以轻松地拖动组件,比如JAVA代码包、JSP、HTML、图片等等,然后将其放到相应的工程结构中。
默认情况下,RAD的自动编译属性是开启的,因此,它会尝试编译并列出任何缺少资源或者未引用的包错误。从我的经验来看,最好由缺少资源的错误开始,然后确保所有需要的应用程序组件已经被成功导入到RAD中。
注意,并不需要导入与Weblogic相关的库或者XML文件。
步骤4:创建web图表
创建web图表是移植过程中最重要的步骤。当创建一个启用Struts的动态Web工程时自动创建一个并未打开的web图表。这个图表是Struts工程的基础;第一步是分析webflow.properties文件和理解从一个节点到另一个节点的转移。注意在上下文中的节点可以是一个JSP页面也可以是一个InputProcessor类。
webflow.properties文件的分析显示第一个节点是index.jsp页面,下一个节点根据确认是否成功要么是computeDay action 要么是index.jsp。从computeDay节点开始,下一个节点是output.jsp。web图表中简单流程在图2中显示。

这里不讨论如何画web图表,因为这超出本文讨论的范围. 请参阅指定的辅导资源。
使用Web图表的优势有二。第一,Web图表提供捕获Webflow 动作顺序的绘图能力。第二,它产生所有在项目Web图表中指定的组件,包括JSP页面和Java代码文件。在移植过程中,可以用这些来产生文件作为模板。例如,可以从Webflow应用中拷贝index.jsp的合适内容到Web图表产生的文件中。
项目结构基本就绪,在下面的步骤中将讨论如何移植项目的模型,视图和控制器。
步骤5:移植视图
移植Webflow应用的视图是相当简单的,首先,移植BEA特有的标签并且用标准的Struts库标签替代它们。
--列表1.移植JSP标签 Webflow: <%@ taglib uri = "WebFlow.tld" prefix="wf" %> Struts: <%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>
其次,在开始的JSP页面替代(如果相应的Struts类可用)或者删除任何BEA特有的import语句。
--列表2.移植JSP include语句 Webflow: <%@ page import="com.beasys.commerce.webflow.WebflowJSPHelper" %>.
在Struts中,import语句不是必需的.用action类的Struts form标签将替代上面的import语句。
最后,用Struts的标准form标签格式替代在Webflow JSP文件中的form标签。在索引JSP页面中,form标签用WebFlowJSPHelper API(应用程序接口)为下一页面创建URL。
具体来说,URL包括页面的名字以及匹配webflow.properties文件当前状态的事件。移植到Struts如下所示:
--列表3.移植JSP form标签Webflow: FORM method="post" action="<%=WebflowJSPHelper.createWebflowURL (pageContext, "index.jsp", button(submit)", false)%>"> --Struts: <html:form method="post" action="/computeDay" > 在struts-config.xml 中的<action-mapping>元素必须有<action>元素如下所示: <action-mapping> <action path="/computeDay" <type="com.ibm.migration.struts.ComputeDay" name="dateData" scope="request" input="/index.jsp" <forward name="success" path="/output.jsp"/> </action-mapping>
接下来,在JSP页面中输入验证和相应Java字节码到标准的Struts输入验证和错误处理. Webflow框架利用validatedform API以及Webflow标签库验证用户输入. Struts提供了标准输入验证和错误处理机制,通过使用ActionErrors和validate()方法在验证在form bean。考虑这个例子:
--列表4.移植JSP验证 --WebFlow JSP 代码: <%@ taglib uri = "WebFlow.tld" prefix="wf" %> 在JSP验证表单的样子: <wf:validatedForm event="submit" namespace="Example"> Year <wf:text name="year"/><br> Month <wf:text name="month"/><br> Day<wf:text name="day"/>< br> <input type="submit" value="Submit" name="submit"/> <wf:validatedForm> --相应的Java代码: ComputeRequest compRequest = new ComputeRequest(); Request.setAttribute("computeRequest", compRequest); ValidatedForm vFrom = ValidatedFormFActory.getValidatedForm(); ValidatedValues vValus = ValidatedValuesFactory.getValidatedValues(request); vForm.validate(vValues, compRequest); vForm.validate(vValues, STRING_VALIDATOR, "year", newMaxExpression(4), "The Year must be four digit" if(vValues.getInvalidFieldCount() > 0) { throw new InvalidFormDataException("Please correct the invalid fields"); } --Struts: public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); If (!year.length() = 3) { errors.add ("year", new ActionError("year-format"); } }
说明Struts如何使用form bean和外在属性文件来处理输入验证和误差,相对于webflow应用误差处理,是捆绑在应用代码上。
步骤6:移植控制器
像这段讨论的,描述一个简单的Webflow应用,输入处理器,或IPs、形成一个典型的Webflow应用的控制器. Struts在actions表单中规定了相当的输入处理器.
下面列示一个简单移植:
--列表6.移植 InputProcessor --Webflow: public class ComputeDayIP extends InPutProcessorSupport Struts: public class ComputeDay extends org.apache.strtus.action.Action
简单说明用Struts的Action类如何取代它的输入处理器.
步骤7:移植模型
Webflow移植应用模型主要包含PipelineSession对象,该对象包括成对的指定值。一旦理解了PipelineSession在特定的文件中是怎样使用的,移植模型就比较容易理解了。
值得注意的是, 通常,Webflow预先的执行程序会将PipelineSession对象存储在HTTPSession中,而不是HTTPRequest中。在Struts里,form bean为等价模型提供了Webflow PipelineSession。
--列表7.移植PipelineSession对象 --Webflow: PipelineSession pSession = null; String namespace = null; pSession = getPipelineSession(req); String year = pSession.getYear(); --Struts: DateData dateData = (DateData) form; year = dateData.getYear();
应用程序的编译和测试
现在,可以使用RAD编译应用程序了。在可用的测试环境中,可以使用工具创建并配置WAR(web 存档文件)。通常,在一个典型的移植项目中,迭代周期需要改变和编译源代码。
RAD版本6提供了用于WebSphere应用服务器6的内置测试环境。在一个真正的移植项目中,一旦使用了RAD单位测试应用程序,就可以在系统移植测试环境(可以将应用程序与外部系统元件整合)做端到端的测试。
结论
这篇文章对使用RAD的开源struts提供了一种逐步的方法来移植BEA Webflow应用。了解了不同组件研发的Webflow应用以及他们是如何影射struts组件的。也了解了怎样创建一个简单的Web图表(利用RAD)以帮助在Webflow应用程序中将导航应用定位到Struts.