# 快速入门开发文档 > @author: youhong.ai >
维护人员: 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 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 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 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 execute(RequestInfo requestInfo) { List 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; /** *

第一个计划任务

*/ 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 ``` ### 如何操作数据库 > 维护人员: