2022-11-24 14:39:42 +08:00
|
|
|
|
# 快速入门开发文档
|
|
|
|
|
|
|
|
|
|
> @author: youhong.ai
|
|
|
|
|
> <br>维护人员: EBU7部开发部
|
|
|
|
|
|
|
|
|
|
## 后端开发
|
|
|
|
|
|
|
|
|
|
### 第一个action
|
|
|
|
|
|
2022-11-26 11:33:21 +08:00
|
|
|
|
> 维护人员:youHong.ai
|
|
|
|
|
|
|
|
|
|
# 附加操作Action/操作者Action相关开发培训
|
|
|
|
|
|
|
|
|
|
### 节点附加操作执行顺序
|
|
|
|
|
|
|
|
|
|
保存表单数据-->节点后附加操作-->生成编号-->出口附加规则-->节点前附加操作-->插入操作者和签字意见
|
|
|
|
|
|
|
|
|
|
注:流程存为文档(workflowToDoc)接口特殊处理,作为流程提交的最后一个action执行
|
|
|
|
|
|
|
|
|
|
#### 如何编写一个action
|
|
|
|
|
|
|
|
|
|
编写一个JAVA类,实现weaver/interfaces/workflow/action/Action.java接口
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package weaver.interfaces.workflow.action;
|
|
|
|
|
|
|
|
|
|
import weaver.soa.workflow.request.RequestInfo;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* User: xiaofeng.zhang
|
|
|
|
|
* Date: 2007-9-7
|
|
|
|
|
* Time: 17:52:53
|
|
|
|
|
* To change this template use File | Settings | File Templates.
|
|
|
|
|
*/
|
|
|
|
|
public interface Action {
|
|
|
|
|
public static final String SUCCESS = "1";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 失败信息,返回此信息,如果是节点前附加操作,将会阻止流程提交
|
|
|
|
|
*/
|
|
|
|
|
public static final String FAILURE_AND_CONTINUE = "0";
|
|
|
|
|
|
|
|
|
|
public String execute(RequestInfo request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
常量 | 值 | 说明
|
|
|
|
|
---|---|---
|
|
|
|
|
SUCCESS | "1" | 成功标识,继续流程提交或执行下一个附加操作
|
|
|
|
|
FAILURE_AND_CONTINUE | "0" | 失败标识,阻断流程提交
|
|
|
|
|
|
|
|
|
|
方法 | 说明
|
|
|
|
|
---|---
|
|
|
|
|
String execute(RequestInfo request); | action实现逻辑,执行时调用此方法
|
|
|
|
|
|
|
|
|
|
实现示例
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package weaver.interfaces.workflow.action.actionDemo;
|
|
|
|
|
|
|
|
|
|
import weaver.general.BaseBean;
|
|
|
|
|
import weaver.interfaces.workflow.action.Action;
|
|
|
|
|
import weaver.soa.workflow.request.RequestInfo;
|
|
|
|
|
|
|
|
|
|
public class BaseActionDemo implements Action {
|
|
|
|
|
@Override
|
|
|
|
|
public String execute(RequestInfo request) {
|
|
|
|
|
|
|
|
|
|
/**********执行action的业务逻辑************/
|
|
|
|
|
new BaseBean().writeLog("我是action,我正在执行");
|
|
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### action参数使用方式
|
|
|
|
|
|
|
|
|
|
使用自定义接口时,可以进行参数设置,和指定参数值。
|
|
|
|
|
|
|
|
|
|
设置后,需在action中实现对应的setter方法,oa会自动将设置的参数值注入
|
|
|
|
|
|
|
|
|
|
如果参数值为数据源,则注入的为DataSource对象,参数值为集成中设置的数据源名称
|
|
|
|
|
|
|
|
|
|
如参数值不为数据源,则注入的值为设置的String对象
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class TestMsgAction implements Action {
|
|
|
|
|
|
|
|
|
|
//action中定义属性,接收参数值,如参数值不为数据源,则注入的值为设置的String对象
|
|
|
|
|
private String aaa = "";
|
|
|
|
|
|
|
|
|
|
//action中定义属性,接收参数值,参数值为数据源,则注入的为DataSource对象
|
|
|
|
|
private DataSource bbb = null;
|
|
|
|
|
|
|
|
|
|
//设置对应的stter方法
|
|
|
|
|
public void setAaa(String aaa) {
|
|
|
|
|
this.aaa = aaa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//设置对应的stter方法
|
|
|
|
|
public void setBbb(DataSource bbb) {
|
|
|
|
|
this.bbb = bbb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String execute(RequestInfo request) {
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### action能做的事情
|
|
|
|
|
|
|
|
|
|
1、获取流程相关信息(requestid、workflowid、formid、isbill、表单信息等);
|
|
|
|
|
|
|
|
|
|
2、执行sql语句,查询或更新OA系统中的数据;
|
|
|
|
|
|
|
|
|
|
3、返回失败标识和提示信息,阻断前台流程提交,并显示提示信息;
|
|
|
|
|
|
|
|
|
|
4、强制收回触发action回滚
|
|
|
|
|
|
|
|
|
|
5、调用第三方系统的接口
|
|
|
|
|
|
|
|
|
|
6、实现自定义操作者
|
|
|
|
|
|
|
|
|
|
#### 实现的方式
|
|
|
|
|
|
|
|
|
|
1、获取流程相关信息
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public String execute(RequestInfo info){
|
|
|
|
|
//获取工作流id
|
|
|
|
|
String workflowId=info.getWorkflowid();
|
|
|
|
|
//获取流程id
|
|
|
|
|
String requestid=info.getRequestid();
|
|
|
|
|
//获取RequestManager对象
|
|
|
|
|
RequestManager RequestManager=info.getRequestManager();
|
|
|
|
|
//获取当前节点id
|
|
|
|
|
int currentnodeid=RequestManager.getNodeid();
|
|
|
|
|
//下一个节点id
|
|
|
|
|
int nextnodeid=RequestManager.getNextNodeid();
|
|
|
|
|
//获取流程表单id
|
|
|
|
|
int formid=RequestManager.getFormid();
|
|
|
|
|
//是否为单据
|
|
|
|
|
int isbill=RequestManager.getIsbill();
|
|
|
|
|
//获取数据库主表名
|
|
|
|
|
String tableName=isbill==1?"workflow_form":RequestManager.getBillTableName();
|
|
|
|
|
return Action.SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2、执行sql语句,查询或更新OA系统中的数据;
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class SQLExecuteActionDemo implements Action {
|
|
|
|
|
@Override
|
|
|
|
|
public String execute(RequestInfo info) {
|
|
|
|
|
//获取流程id
|
|
|
|
|
String requestid = info.getRequestid();
|
|
|
|
|
|
|
|
|
|
/*************1.不带事务执行SQL开始***************/
|
|
|
|
|
RecordSet rs = new RecordSet();
|
|
|
|
|
//执行查询语句,查询数据
|
|
|
|
|
rs.executeQuery("select testFieldName from formtable_main_45 where requestid = ?", requestid);
|
|
|
|
|
if (rs.next()) {
|
|
|
|
|
String testFieldValue = rs.getString(1);
|
|
|
|
|
new BaseBean().writeLog("testFieldName 的值是 :" + testFieldValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//执行update语句,更新数据
|
|
|
|
|
rs.executeUpdate("update formtable_main_45 set testFieldName = ? where requestid = ?", "testValue", requestid);
|
|
|
|
|
/*************1.不带事务执行SQL结束***************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************2.带事务执行SQL开始***************/
|
|
|
|
|
RecordSetTrans rst = new RecordSetTrans();
|
|
|
|
|
rst.setAutoCommit(false);
|
|
|
|
|
try {
|
|
|
|
|
rst.executeUpdate("update formtable_main_45 set testFieldName1 = ? where requestid = ?", "testValue1", requestid);
|
|
|
|
|
|
|
|
|
|
rst.executeUpdate("update formtable_main_45 set testFieldName2 = ? where requestid = ?", "testValue2", requestid);
|
|
|
|
|
|
|
|
|
|
//手动提交事务
|
|
|
|
|
rst.commit();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
//执行失败,回滚数据
|
|
|
|
|
rst.rollback();
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
/*************2.带事务执行SQL结束***************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************3.查询或操作流程流转相关表开始***************/
|
|
|
|
|
/*************此处需注意不要将RecordSetTrans对象的事务提交掉***************/
|
|
|
|
|
RecordSetTrans requestRst = info.getRequestManager().getRsTrans();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
requestRst.executeQuery("select status from workflow_requestbase where requestid = ?", requestid);
|
|
|
|
|
if (requestRst.next()) {
|
|
|
|
|
String statusValue = rs.getString("status");
|
|
|
|
|
new BaseBean().writeLog("statusValue 的值是 :" + statusValue);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************3.查询或操作流程流转相关表结束***************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Action.SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> 注意点1:操作OA数据库中数据,必须使用OA自带的数据库操作类(推荐Recordet、RecordSetTrans),使用其他方式操作数据库,可能会出现数据库缓存读取不到最新数据的情况
|
|
|
|
|
|
|
|
|
|
> 注意点2:使用requestInfo.getRequestManager().getRsTrans()获取到的RecordSetTrans对象,不要手动提交或者回滚数据,会导致流程提交错误。
|
|
|
|
|
|
|
|
|
|
3、返回失败标识和提示信息,阻断前台流程提交,并显示提示信息;
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public String execute(RequestInfo request){
|
|
|
|
|
|
|
|
|
|
//获取requestId
|
|
|
|
|
String requestId=request.getRequestid();
|
|
|
|
|
|
|
|
|
|
float amount=0;
|
|
|
|
|
|
|
|
|
|
/*************1.直接查询数据库获取表单值***************/
|
|
|
|
|
RecordSet rs=new RecordSet();
|
|
|
|
|
rs.executeQuery("select amount from formtable_main_16 where requestid = ?",requestId);
|
|
|
|
|
//获取金额字段的值
|
|
|
|
|
if(rs.next()){
|
|
|
|
|
amount=rs.getFloat(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************2.直接查询数据库获取表单值***************/
|
|
|
|
|
//获取主表数据
|
|
|
|
|
Map<String, String> mainDatas=new HashMap<>();
|
|
|
|
|
Property[]properties=request.getMainTableInfo().getProperty();
|
|
|
|
|
for(Property propertie:properties){
|
|
|
|
|
mainDatas.put(propertie.getName(),propertie.getValue());
|
|
|
|
|
}
|
|
|
|
|
amount=Util.getFloatValue(Util.null2String(mainDatas.get("amount")));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//金额字段值大于10000,阻断流程提交
|
|
|
|
|
if(amount>10000){
|
|
|
|
|
RequestManager requestManager=request.getRequestManager();
|
|
|
|
|
requestManager.setMessagecontent("不允许提交金额大于10000的流程");
|
|
|
|
|
return FAILURE_AND_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4、强制收回触发action回滚
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public String execute(RequestInfo request){
|
|
|
|
|
|
|
|
|
|
//获取requestId
|
|
|
|
|
String requestId=request.getRequestid();
|
|
|
|
|
|
|
|
|
|
//对应节点强制收回,则回滚数据
|
|
|
|
|
if(request.getRequestManager().getNodeid()==123){
|
|
|
|
|
RecordSet rs=new RecordSet();
|
|
|
|
|
rs.executeUpdate("delete from uf_fix_log where requestid = ?",requestId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> 注意点:所有节点执行强制收回或者删除都会执行,需在action中判断当前节点Id
|
|
|
|
|
|
|
|
|
|
5、调用第三方系统的接口
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package weaver.interfaces.workflow.action.actionDemo;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
import weaver.conn.RecordSet;
|
|
|
|
|
import weaver.general.BaseBean;
|
|
|
|
|
import weaver.interfaces.workflow.action.Action;
|
|
|
|
|
import weaver.soa.workflow.request.Property;
|
|
|
|
|
import weaver.soa.workflow.request.RequestInfo;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
public class HttpTestAction implements Action {
|
|
|
|
|
@Override
|
|
|
|
|
public String execute(RequestInfo requestInfo) {
|
|
|
|
|
|
|
|
|
|
//打印日志对象
|
|
|
|
|
BaseBean baseBean = new BaseBean();
|
|
|
|
|
baseBean.writeLog("获取到归属地action执行 requestid = " + requestInfo.getRequestid());
|
|
|
|
|
|
|
|
|
|
Map<String, String> mainTableDatas = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
//获取主表字段数据
|
|
|
|
|
Property[] properties = requestInfo.getMainTableInfo().getProperty();
|
|
|
|
|
for (Property property : properties) {
|
|
|
|
|
mainTableDatas.put(property.getName(), property.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?";
|
|
|
|
|
String result = httpUtil(url, "tel=" + mainTableDatas.get("dhhm"));
|
|
|
|
|
|
|
|
|
|
String results[] = result.split("=");
|
|
|
|
|
if (result.length() > 1) {
|
|
|
|
|
JSONObject object = JSONObject.parseObject(results[1]);
|
|
|
|
|
//获取到归属地
|
|
|
|
|
String carrier = (String) object.get("carrier");
|
|
|
|
|
baseBean.writeLog("获取到归属地 :" + carrier);
|
|
|
|
|
RecordSet rs = new RecordSet();
|
|
|
|
|
String sql = "update formtable_main_199 set gsd = ? where requestid = ?";
|
|
|
|
|
rs.executeUpdate(sql, carrier, requestInfo.getRequestid());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String httpUtil(String path, String data) {
|
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
|
|
|
try {
|
|
|
|
|
URL url = new URL(path);
|
|
|
|
|
//打开url的连接
|
|
|
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
|
|
//设置请求方式
|
|
|
|
|
conn.setRequestMethod("POST");
|
|
|
|
|
conn.setDoOutput(true);
|
|
|
|
|
conn.setDoInput(true);
|
|
|
|
|
|
|
|
|
|
PrintWriter out = new PrintWriter(conn.getOutputStream());
|
|
|
|
|
//发送请求参数
|
|
|
|
|
out.print(data);
|
|
|
|
|
out.flush();
|
|
|
|
|
//获取响应输入流
|
|
|
|
|
InputStream is = conn.getInputStream();
|
|
|
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(is, "GBK"));
|
|
|
|
|
String str = "";
|
|
|
|
|
while ((str = br.readLine()) != null) {
|
|
|
|
|
result.append(str);
|
|
|
|
|
}
|
|
|
|
|
//关闭输入流
|
|
|
|
|
is.close();
|
|
|
|
|
conn.disconnect();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result.toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
6、实现自定义操作者
|
|
|
|
|
|
|
|
|
|
> 需实现weaver/interfaces/workflow/action/OperatorAction.java接口
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package weaver.interfaces.workflow.action;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
import weaver.soa.workflow.request.RequestInfo;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 流程节点操作者自定义接口
|
|
|
|
|
* @author Mcr
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public interface OperatorAction {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 取节点操作者,返回人员id集合
|
|
|
|
|
* @param requestInfo
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public List<String> execute(RequestInfo requestInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
实现示例:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package weaver.interfaces.workflow.action.actionDemo;
|
|
|
|
|
|
|
|
|
|
import weaver.interfaces.workflow.action.OperatorAction;
|
|
|
|
|
import weaver.soa.workflow.request.RequestInfo;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
public class OperatorActionTest implements OperatorAction {
|
|
|
|
|
/**
|
|
|
|
|
* 取节点操作者,返回人员id集合
|
|
|
|
|
*
|
|
|
|
|
* @param requestInfo
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public List<String> execute(RequestInfo requestInfo) {
|
|
|
|
|
|
|
|
|
|
List<String> operatorList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
//返回人员id
|
|
|
|
|
operatorList.add("21");
|
|
|
|
|
operatorList.add("22");
|
|
|
|
|
|
|
|
|
|
return operatorList;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
7、流程提交失败,调用action回滚逻辑(E9+2006KB支持)
|
|
|
|
|
|
|
|
|
|
8、节点附加操作执行失败问题的简单排查
|
2022-11-24 14:39:42 +08:00
|
|
|
|
|
|
|
|
|
### 第一个定时任务
|
|
|
|
|
|
|
|
|
|
> 维护人员:
|
|
|
|
|
|
|
|
|
|
### 第一个restful接口
|
|
|
|
|
|
|
|
|
|
> 维护人员:
|
|
|
|
|
|
|
|
|
|
### 如何操作数据库
|
|
|
|
|
|
|
|
|
|
> 维护人员:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|