泛微后台开发的其中一种,是 Action 类的开发。Action 类必须实现 weaver.interfaces.workflow.action.Action 接口,并在其 execute(RequestInfo request) 方法中按需返回 Action.SUCCESS 或者 Action.FAILURE_AND_CONTINUE 来达到控制流程走向的目的。
- 关于配置创建环节的节点前操作,该流程的行为:
如果为流程配置了节点前操作,而该流程是由外部接口等调用发起的(即:不是点击泛微自己的界面发起)、那么节点前操作将不会生效。
- 关于 execute(RequestInfo request) 返回后,该流程的行为:
如果返回的是 Action.SUCCESS ,则流程会根据当前节点配置的出口条件,继续进行流转;如没有符合条件的出口,则停留在当前节点的表单界面并报错。
如果返回的是 Action.FAILURE_AND_CONTINUE ,则流程会无条件停留在当前节点的表单界面并报错。
- 关于配置节点后操作,该流程的行为:
流程节点页面单击"批准"时,或者其他外部接口触发批准该节点时,该节点的所有"节点后操作"都会按顺序被执行。
流程节点页面单击"退回"时,仅该节点设置了"退回时触发"的"节点后操作"才会按顺序被执行。
当"节点后操作"是 Action 类,且在运行过程中抛出异常,将会被 BaseAction 类捕获并写入日志;流程将停留在当前环节的界面,并提示"节点后操作失败"。
当需要主动设置或更改流程中的表单字段,并令其保存到下一环节、需要直接用 sql 将数据更新到数据库中。目前直接用 Java 代码修改表单的 Property 等对象属性,只能在内存中操作、并不能保存到下一环节。
来看下两种代码的区别:
package com.acme.weaver.oa.actions;
import com.weaver.general.BaseBean;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.*;
/**
*这是只能在表单层面修改和读取变化(不能保存到下一环节)的代码
*@author luobenyu
*/
public class MyCustomAction extends BaseBean implements Action {
@Override
public String execute(RequestInfo request){
Property[] mainProps = request.getMainTableInfo().getProperty();
// 要修改的主表字段
String mainField = "field101";
// 该主表字段修改后的值
String mainFieldValue = "value101";
for(int i=0; i< mainProps.length; i++){
if(mainProps[i].getName().equals(mainField)){ //主表中存在此字段
prop = mainProps[i];
prop.setValue(mainFieldValue);
request.getMainTableInfo().setProperty(i,prop);
}
}
// 调用 BaseBean 的写日志方法
// 会将日志写入泛微 E8 根目录的 /log/ecology 文件中
this.writeLog("已完成修改,仅用于 Java 缓存读取,不可用于全流程");
// 返回 SUCCESS 则依次进入: 当前环节的其他【节点后操作】、系统的出口条件判断、下一环节的【节点前操作】
// 返回 FAILURE_AND_PASS 则会停留在当前环节的界面,提交不成功
return Action.SUCCESS;
}
}
另一种方式就。。很简朴。。。
package com.acme.weaver.oa.actions;
import com.weaver.general.BaseBean;
import weaver.conn.RecordSet;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.*;
/**
*这是可用于全流程修改和读取变化(保存到下一环节)的代码
* @author luobenyu
*/
public class MyCustom2Action extends BaseBean implements Action {
@Override
public String execute(RequestInfo request){
Property[] mainProps = request.getMainTableInfo().getProperty();
// 要修改的主表名称
String mainTableName = request.getRequestManager().getBillTableName();
// 要修改的对应记录行号
String requestId = request.getRequestid();
// 要修改的主表字段
String mainField = "field101";
// 该主表字段修改后的值
String mainFieldValue = "value102";
RecordSet rs = new RecordSet(); //直接更新数据库内容,控制流程走向
String sql = "update "+ mainTableName +" set "+mainField+"= '"+mainFieldValue+"' where requestid ="+requestId;
rs.execute(sql);
// 调用 BaseBean 的写日志方法
// 会将日志写入泛微 E8 根目录的 /log/ecology 文件中
this.writeLog("已完成修改,可用于全流程");
// 返回 SUCCESS 则依次进入: 当前环节的其他【节点后操作】、系统的出口条件判断、下一环节的【节点前操作】
// 返回 FAILURE_AND_PASS 则会停留在当前环节的界面,提交不成功
return Action.SUCCESS;
}
}
- 关于配置流程出口权限后,该流程的行为:
流程配置中,如果多个出口都拥有相同的"源节点",那么将永远优先执行无条件的那个出口;此时同一个"源节点"其他含条件的出口将永远不被执行。即使在该"源节点"后使用 Action 类的方法进行判断,该 Action 类对表单的赋值操作,也不会生效。
解决的办法通常是,将原来的“无条件执行”的出口,设置与其他有条件出口互斥的一组条件来执行。这样新增的有条件的出口就可以生效了。(最容易出问题的其实是这里)
- 关于获取流程当前节点信息的操作:
获取流程当前 objid 可以调用以下代码。
package com.acme.weaver.oa.actions;
import com.weaver.general.BaseBean;
import weaver.conn.RecordSet;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.*;
/**
*读取流程节点 id
* @author luobenyu
*/
public class MyCustom3Action extends BaseBean implements Action {
@Override
public String execute(RequestInfo request){
String objid = request.getObjid();
// 返回 SUCCESS 则依次进入: 当前环节的其他【节点后操作】、系统的出口条件判断、下一环节的【节点前操作】
// 返回 FAILURE_AND_PASS 则会停留在当前环节的界面,提交不成功
return Action.SUCCESS;
}
}
获取流程当前节点,可以参考以下 SQL / Java 代码来实现。
/**
* 获取执行action的环节类型
* @param objid
* @return
*/
public String getRESULTFLAG(String objid){
String RESULTFLAG = "";
if(objid.equals("")){
return "";
}
RecordSet rs = new RecordSet();
String sql = "select t.isstart,t.isend from workflow_nodebase t where t.id = '" + objid +"'" ;
rs.execute(sql);
if(rs.next()){
String isstart = rs.getString("ISSTART");
String isend = rs.getString("ISEND");
if(isstart.equals("1")){
RESULTFLAG = "F";
}else if(isend.equals("1")){
RESULTFLAG = "Y";
}else{
RESULTFLAG = "N";
}
}
return RESULTFLAG;
}
- 关于获取该流程当前节点的操作状态:
当前节点的操作状态分别有提交、暂存、退回 共3种状态。分别对应的值是 "submit", "save","reject"。获取当前节点操作状态的代码参考如下:
/**
* RequestInfo 类型的对象: requestInfo
* "reject"代表退回,"save"代表暂存(未提交到下一节点),"submit"代表提交
*/
requestInfo.getRequestManager().getSrc();
将 Action 类开发完成后,首先将编译好的 .class 文件上传到服务器的 classbean 目录下的对应路径。然后如图进行注册。完成注册后,就可以被流程引用了。
先写这么多,后续有踩到的坑、再补充上来。
(完)