struts2与jbpm4的简单集成

当公司领导指定使用struts2作为某项目的显示层实现技术时,而该项目使用了jbpm。
当使用jbpm时,正常情况下是要显示未知数量的业务表单页面。
一般情况下,在使用struts2(本人使用的情况下)的一般情况下,页面控制是已经写在struts的配置文件当中,也就是说要显示的页面基本是已知的了(未知页面,显然是无法配置的),因此一般情况下,当有新业务时,或者业务流程发生变化时(任务节点新增与删除等),就会导致业务表单页面的新增与删除,然后这种以xml配置方式,显然是无法满足需求的。
我们知道在使用springmvc时,viewname是可以在程序里指定,这样业务表单也是可以在程序里指定的,可以避免xml配置的不灵活性。显然struts2肯定也应该提供了这样的方式。
扩展以下两个类即可:
1、StrutsActionProxyFactory;
2、DefaultActionInvocation;

我们需要覆盖DefaultActionInvocation.createResult方法,
因为该方法的默认实现是从resultmappings里根据resultcode(action相关方法返回值)获取视图的,因此如果业务表单为在struts2的配置文件里进行配置,应该是会抛出异常。因此,我们只要覆盖该方法,并根据resultcode寻找视图(而不是从resultmapping里寻找)。一般情况,resultcode可以是业务表单页面的相对路径。

为了使用我们自己的ActionInvocation,就必须覆盖StrutsActionProxyFactory.createActionProxy方法,因为该方法已经指定返回StrutsActionProxy,我们覆盖StrutsActionProxyFactory.createActionProxy方法,返回我们自己的ActionInvocation。

具体实现如下:
public class IcomStrutsActionInvocation extends DefaultActionInvocation {

public static final String JBPM_PREFIX = "icom:";

public IcomStrutsActionInvocation(Map<String, Object> extraContext, boolean pushAction) {
super(extraContext, pushAction);
}

/**
*
*/
private static final long serialVersionUID = 1L;

public Result createResult() throws Exception {

if (resultCode != null && resultCode.startsWith(JBPM_PREFIX)) {// 如果是工作流表单(返回代码必须以icom:开头哦)
Map<String, String> resultParams = new HashMap<String, String>();
resultParams.put("location", resultCode.replace(JBPM_PREFIX, ""));
ResultConfig resultConfig = new ResultConfig.Builder(resultCode,
ServletDispatcherResult.class.getName()).addParams(resultParams)
.build();

return objectFactory.buildResult(resultConfig, invocationContext
.getContextMap());
} else {
return super.createResult();
}

}

}


public class IcomStrtuts2ActionFactory extends StrutsActionProxyFactory {

public ActionProxy createActionProxy(String namespace, String actionName,
String methodName, Map<String, Object> extraContext,
boolean executeResult, boolean cleanupContext) {

ActionInvocation inv = new IcomStrutsActionInvocation(extraContext, true);
container.inject(inv);

return super.createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
}


}


因为struts-default.xml文件是没有配置我们自己的实现类,因此需要在struts的配置文件添加我们自己的相关实现类,配置如下:
<struts>
<bean class="com.icom.tech.struts2.IcomStrtuts2ActionFactory"
name="default" type="com.opensymphony.xwork2.ActionProxyFactory" />
...
</struts>


struts-action返回resultcode例子:
public String forTask() throws Exception {

TaskService taskService = processEngine.getTaskService();
task = taskService.getTask(taskId);
if (null == task)
throw new NullPointerException("id为:" + taskId + " 的任务已经被处理...");
taskService.getVariableNames(taskId);
Map<String, Object> variables = taskService.getVariables(taskId,
taskService.getVariableNames(taskId));
if (!(null == variables || variables.isEmpty())) {
ValueStack stack = ActionContext.getContext().getValueStack();
Iterator<String> it = variables.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
logger.info("将要压入的参数:" + key + " 值为:" + variables.get(key));
Object value = variables.get(key);
stack.set(key, value);
}
}
if(flag){
// 获取表单页面路径信息
return IcomStrutsActionInvocation.JBPM_PREFIX+retriveFormResource();
}


return IcomStrutsActionInvocation.JBPM_PREFIX
+ task.getFormResourceName();
}



private String retriveFormResource() throws Exception {

String formResourceName = task.getFormResourceName();

String excutionId = task.getExecutionId();

Execution e = processEngine.getExecutionService().findExecutionById(
excutionId);

ProcessDefinition pd = processEngine.getRepositoryService()
.createProcessDefinitionQuery().processDefinitionId(
e.getProcessDefinitionId()).uniqueResult();

DeploymentImpl deployment = (DeploymentImpl) processEngine
.getRepositoryService().createDeploymentQuery().deploymentId(
pd.getDeploymentId()).uniqueResult();


String path = deployment.getId() + "/" + pd.getId() + "/"
+ formResourceName;
File formFile = new File(formBaseDir, path);

// 首先判断文件是否存在,不存在则创建表单文件
if (!formFile.exists())

synchronized (processEngine) {
if(!formFile.getParentFile().exists()){
formFile.getParentFile().mkdirs();
}

byte[] buf = deployment.getBytes(formResourceName);

// 写入特定存放目录中
FileOutputStream fos = new FileOutputStream(formFile);
fos.write(buf);
fos.close();
}

return DEFAULT_FORM_BASE_DIR + path;
}


以下是jpdl编写的流程定义文件片段:
<task assignee="${user}" name="材料补正" form="printSupplyMaterial.jsp">
<on event="start">
<event-listener factory="businessInstanceListener" method="getInstance" />
</on>
<on event="timeout">
<timer duedate="${tc_supplyMaterial_timeout}" />
<event-listener class="com.icom.cpb.workflow.listener.ChangeColorListener" auto-wire="true" >
<property name="fontColor">
<string value="${tc_supplyMaterial_timeout_color}"/>
</property>
<property name="businessInstanceService">
<ref object="businessInstanceService"/>
</property>
</event-listener>
</on>
<transition name="未补全" to="不受理" >
<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
<property name="userInfoService">
<ref object="userInfoService" />
</property>
<property name="docNumberService">
<ref object="docNumberService" />
</property>
<property name="docnumberName">
<string value="不予受理" />
</property>
<property name="variableName">
<string value="recode" />
</property>
</event-listener>
<event-listener class="com.icom.cpb.workflow.listener.ResetCreateTimeListener">
<property name="businessInstanceService">
<ref object="businessInstanceService"/>
</property>
</event-listener>
</transition>
<!--
<transition name="已补全" to="受理" >
<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
<property name="userInfoService">
<ref object="userInfoService" />
</property>
<property name="docNumberService">
<ref object="docNumberService" />
</property>
<property name="docnumberName">
<string value="受理" />
</property>
<property name="variableName">
<string value="accode" />
</property>
</event-listener>
</transition>
-->
<transition name="已补全" to="受理" >
<event-listener class="com.icom.cpb.workflow.listener.ClearMaterialsListener" >
<property name="businessInstanceService">
<ref object="businessInstanceService"/>
</property>
<property name="receivedDocInfoService">
<ref object="receivedDocInfoService"/>
</property>
</event-listener>
<event-listener class="com.icom.cpb.workflow.listener.ResetCreateTimeListener">
<property name="businessInstanceService">
<ref object="businessInstanceService"/>
</property>
</event-listener>
<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
<property name="userInfoService">
<ref object="userInfoService" />
</property>
<property name="docNumberService">
<ref object="docNumberService" />
</property>
<property name="docnumberName">
<string value="受理" />
</property>
<property name="variableName">
<string value="accode" />
</property>
</event-listener>
</transition>
</task>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值