最近在学习Snaker工作流,在Git上(下载地址)下载了一份代码,跑通后简单用了一下功能,(建议使用IE浏览器,其他浏览器会出现页面显示不完整的情况)对时间相关的几个属性一头雾水,调试了代码,感觉这份代码里没有实现这几个功能,于是在网上找了些相关资料,自己在项目中添加了该功能(不知道作者是不是这样的实现思路)
图中标记的几处,我的理解是 ,第一张图里设置的期望完成时间是总流程的期望完成时间,即系统时间超过该时间这个流程就更改状态为已结束,第二张图里设置的期望完成时间是该节点的结束时间,如果“是否自动执行”为“是”,超过该时间流程就自动走到下一节点,反之则停留在该节点,直至整个流程结束。
思考一下,此处设置的时间何时生效?是在保存流程时生效还是启动流程时生效?应该是在启动流程的时候吧。通过F12找到启动时调用的接口为http://localhost:8080/config/form/submit,在项目中找到该方法,在该方法中加上设置的时间即可,这是我的思路,接下来就想办法实现代码吧!
首先引入需要的jar包,如果你不是maven工程,需要下载jar包,下载地址https://mvnrepository.com/artifact/com.github.snakerflow/snaker-quartz/2.5.1,点击jar即可,将下载jar包导入项目中。
其次在snaker.xml中配置时限控制的拦截器、定时调度的实现类
以上两步已经完成了时限的配置工作,下面就可以针对提醒、超时自动执行做自定义扩展了。
接下来编写自定义的提醒类,实现IRminder接口,并在snaker.xml中配置
package com.snakerflow.framework.flow.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.snaker.engine.entity.Process;
import org.snaker.engine.model.NodeModel;
import org.snaker.engine.scheduling.IReminder;
import java.util.Map;
/**
* @author Lebron
* @ClassName SnakerReminder
* @Description 提醒类 TODO
* @Date 2020/4/22 15:45
* @Version 1.0
*/
public class SnakerReminder implements IReminder {
private static Log logger = LogFactory.getLog(SnakerReminder.class);
@Override
public void remind(Process process, String orderId, String taskId, NodeModel nodeModel, Map data) {
logger.info("orderId:" + orderId);
logger.info("taskId:" + taskId);
logger.info("process:" + process.getDisplayName());
logger.info("nodeModel:" + nodeModel.getDisplayName());
for (String key : data.keySet()) {
logger.info(key + ":" + data.get(key));
}
}
}
回调类代码,回调类的路径也需要配置在工作流中!
package com.snakerflow.framework.flow.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.snaker.engine.entity.Task;
import org.snaker.engine.scheduling.JobCallback;
import java.util.List;
/**
* @author Lebron
* @ClassName SnakerJobCallback
* @Description 回调类 TODO
* @Date 2020/4/22 15:47
* @Version 1.0
*/
public class SnakerJobCallback implements JobCallback {
private static Log logger = LogFactory.getLog(SnakerReminder.class);
@Override
public void callback(String taskId, List newTasks) {
logger.info("taskId:" + taskId);
}
}
最后在启动流程方法中加入配置时间的代码即可,将submit方法修改为
@RequestMapping(value = "submit", method = RequestMethod.POST)
public String submit(HttpServletRequest request, long formId) {
String processId = request.getParameter(PARA_PROCESSID);
String orderId = request.getParameter(PARA_ORDERID);
String taskId = request.getParameter(PARA_TASKID);
List fields = dynamicFormManager.getFields(formId);
Map params = new HashMap();
for (Field field : fields) {
if (Field.FLOW.equals(field.getFlow())) {
String name = field.getName();
String type = field.getType();
String paraValue = request.getParameter(name);
Object value = null;
if ("text".equalsIgnoreCase(type)) {
value = paraValue;
} else if ("int".equalsIgnoreCase(type)) {
if (paraValue == null || "".equals(paraValue)) {
value = 0;
} else {
try {
value = Integer.parseInt(request.getParameter(name));
} catch (Exception e) {
value = 0;
}
}
} else if ("float".equalsIgnoreCase(type)) {
if (paraValue == null || "".equals(paraValue)) {
value = 0.0;
} else {
try {
value = Double.parseDouble(request.getParameter(name));
} catch (Exception e) {
value = 0.0;
}
}
} else {
value = paraValue;
}
params.put(name, value);
}
}
Map paraMap = request.getParameterMap();
if (!orderId.equals("") || !taskId.equals("")) {
dynamicFormManager.submit(formId, fields, params, request, processId, orderId, taskId);
} else {
Map args = new HashMap();
args.put("time.expireTime", new DateTime(2020, 4, 27, 19, 00).toDate());
args.put("time1.reminderTime", new Date());
args.put("time1.expireTime", new Date());
args.put("time2.reminderTime", new DateTime(2020, 4, 27, 14, 05).toDate());
args.put("time2.expireTime", new DateTime(2020, 4, 27, 14, 10).toDate());
engine.startInstanceById(processId, "admin", args);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (StringUtils.isNotEmpty(processId)) {
return "redirect:/snaker/task/active";
} else {
return "redirect:/config/form";
}
}
这段代码的属性值根据自己的流程图文件定义,这里我在流程图里定义了变量,下面是我的流程文件,另外如果需要多次提醒的话,需要在snaker.properties中配置snaker.properties,是一个数字,表示提醒的次数。
从代码中可以看出,我希望这个流程在19:00结束,第一个节点在流程启动的同时执行,第二个节点在14:05提醒,提醒间隔为2分钟,并且在14:10到达期望完成时间,如果到达14:10没有执行,则自动执行,即整个流程走完。通过打断点可以测试出,提醒方式是查询到的流程信息打印在控制台,大家可以根据需求自行编写代码。