ebu_ecology_dev1/快速入门开发.md

512 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 快速入门开发文档
> @author: youhong.ai
> <br>维护人员: EBU7部开发部
## 后端开发
### 第一个action
> 维护人员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、节点附加操作执行失败问题的简单排查
> 查看日志文件 /ecology/log/integration/integration_流程提交日期.log 文件中根据requestid进行搜索会有详细的接口后附加操作的相关日志。
### 第一个定时任务
> 维护人员weilin.zhu
> 必须继承weaver.interfaces.schedule.BaseCronJob类实现execute() 方法。
``` java
import weaver.interfaces.schedule.BaseCronJob;
/**
* <p>第一个计划任务</p>
*/
public class FirstTask extends BaseCronJob {
/**
* 自定义参数 必须有getter、setter方法否则无法取到配置值
*/
private String cusParam = "";
/**
* 重写父类方法
*/
@Override
public void execute() {
//具体的业务逻辑
}
public String getCusParam() {
return cusParam;
}
public void setCusParam(String cusParam) {
this.cusParam = cusParam;
}
}
```
### 第一个restful接口
> 维护人员weilin.zhu
> 1、API接口必须写在 com.api /om.cloudstore 文件夹下这样才能被扫描到。若系统有统一待办的非标功能放在weaver.rest目录下也是可以的。
>
> 2、但是这里我们这边要求大家放到 com.api 目录下,我们编写的接口,请求地址前面默认会加上/api。例@Path("/getUserInfo"),请求地址应为/api/getUserInfo
>
> 3、若编写的api供外部系统调用必须将api的请求地址放在配置文件的白名单中否则异构系统无法直接调用。
> 关于API白名单说明
>
> 配置文件ecology/WEB-INF/prop/weaver_session_filter.properties
>
> 配置说明在unchecksessionurl=后面添加自定义接口请求地址
> 示例代码:
```java
```
### 如何操作数据库
> 维护人员: