1.启动流程并分配任务是单个流程的正式开始,因此要使用到runtimeService接口,以及相关的启动流程的方法。我习惯于用流程定义的key启动,因为有多个版本的流程定义时,用key启动默认会使用最新版本。同时,因为启动中查询了流程部署时xml文件中流程节点的信息,也用到了repositoryService及相关方法。
2.后台业务代码,
(1)自定义的申请单实体类(为的目的只为了跑通整个流程,因此只定义了一个实体类,按公司标准开发来说,应该是和前台交互一个command类(其实也还是实体类,叫法不一样而已),和数据库交互还有一个实体类),在这里定义了一个申请单的基本信息:
[java]
view plain copypackage model;
public class applyModel {
/**
* 流程定义id
*/
private String proDefId;
/**
* 流程定义的key
*/
private String key;
private String name;
/**
* 申请人
*/
private String appPerson;
/**
* 原因
*/
private String cause;
/**
* 内容
*/
private String content;
/**
* 处理人,即下一个任务节点的受理人
*/
private String proPerson;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getAppPerson() {
return appPerson;
}
public void setAppPerson(String appPerson) {
this.appPerson = appPerson;
}
public String getCause() {
return cause;
}
public void setCause(String cause) {
this.cause = cause;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getProPerson() {
return proPerson;
}
public void setProPerson(String proPerson) {
this.proPerson = proPerson;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProDefId() {
return proDefId;
}
public void setProDefId(String proDefId) {
this.proDefId = proDefId;
}
@Override
public String toString() {
return "applyModel [proDefId=" + proDefId + ", key=" + key + ", name="
+ name + ", appPerson=" + appPerson + ", cause=" + cause
+ ", content=" + content + ", proPerson=" + proPerson + "]";
}
}
(2)业务逻辑:
A,这个方法获取流程部署时xml文件里的各个节点相关信息,用来辨别当前是哪个节点,下一节点又是什么,共下边的B方法调用。因为操作部署时的文件,因此使用repositoryService:
[java]
view plain copy/**
* @throws XMLStreamException
* 查询流程节点
*
* @author:tuzongxun
* @Title: findFlow
* @param @return
* @return Iterator<FlowElement>
* @date Mar 21, 2016 9:31:42 AM
* @throws
*/
public Iterator<FlowElement> findFlow(String processDefId)
throws XMLStreamException {
List<ProcessDefinition> lists = repositoryService
.createProcessDefinitionQuery()
.processDefinitionId(processDefId)
.orderByProcessDefinitionVersion().desc().list();
ProcessDefinition processDefinition = lists.get(0);
processDefinition.getCategory();
String resourceName = processDefinition.getResourceName();
InputStream inputStream = repositoryService.getResourceAsStream(
processDefinition.getDeploymentId(), resourceName);
BpmnXMLConverter converter = new BpmnXMLConverter();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
BpmnModel bpmnModel = converter.convertToBpmnModel(reader);
Process process = bpmnModel.getMainProcess();
Collection<FlowElement> elements = process.getFlowElements();
Iterator<FlowElement> iterator = elements.iterator();
return iterator;
}
B.这里调用上一个方法,一起完成流程的启动及相关信息的设置:
[java]
view plain copy/**
* @throws XMLStreamException
* 启动流程
*
* @author:tuzongxun
* @Title: startProcess
* @param @return
* @return Object
* @date Mar 17, 2016 2:06:34 PM
* @throws
*/
@RequestMapping(value = "/startProcess.do", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
@ResponseBody
public Object startProcess(@RequestBody applyModel applyModel,
HttpServletRequest req) throws XMLStreamException {
Map<String, String> map = new HashMap<String, String>();
boolean isLogin = this.isLogin(req);
if (isLogin) {
if (applyModel != null) {
String processKey = applyModel.getKey();
String processDefId = applyModel.getProDefId();
// //////////////////////////
Iterator<FlowElement> iterator = this.findFlow(processDefId);
Map<String, Object> varables = new HashMap<String, Object>();
int i = 1;
while (iterator.hasNext()) {
FlowElement flowElement = iterator.next();
// 申请人
if (flowElement.getClass().getSimpleName()
.equals("UserTask")
&& i == 1) {
UserTask userTask = (UserTask) flowElement;
String assignee = userTask.getAssignee();
int index1 = assignee.indexOf("{");
int index2 = assignee.indexOf("}");
varables.put(assignee.substring(index1 + 1, index2),
applyModel.getAppPerson());
varables.put("cause", applyModel.getCause());
varables.put("content", applyModel.getContent());
varables.put("taskType", applyModel.getName());
i++;
// 下一个处理人
} else if (flowElement.getClass().getSimpleName()
.equals("UserTask")
&& i == 2) {
UserTask userTask = (UserTask) flowElement;
String assignee = userTask.getAssignee();
int index1 = assignee.indexOf("{");
int index2 = assignee.indexOf("}");
varables.put(assignee.substring(index1 + 1, index2),
applyModel.getProPerson());
break;
}
}
// ///////////////////////////
runtimeService.startProcessInstanceByKey(processKey, varables);
map.put("userName",
(String) req.getSession().getAttribute("userName"));
map.put("isLogin", "yes");
map.put("result", "success");
} else {
map.put("result", "fail");
}
} else {
map.put("isLogin", "no");
}
return map;
}
3.angular js前台代码,:
(1)app.js中配置路由:
[javascript]
view plain copy$stateProvider
.state('startProcess', {
url: "/startProcess",
views: {
'view': {
templateUrl: 'activi_views/startProcess.html',
controller: 'startProcessCtr'
}
}
});
(2)逻辑相关代码:
[javascript]
view plain copyangular.module('activitiApp')
.controller('startProcessCtr', ['$rootScope','$scope','$http','$location', function($rootScope,$scope,$http,$location){
$http.post("createFlush.do").success(function(result){
if(result.isLogin==="yes"){
$rootScope.userName=result.userName;
$scope.process1={"proDefId":"","key":"","appPerson":"","cause":"","content":"","proPerson":"","name":""};
if($rootScope.process==null||$rootScope.process.key==null){
$location.path("/processList");
}else{
$scope.process1.proDefId=$rootScope.process.id;
$scope.process1.key=$rootScope.process.key;
$scope.process1.name=$rootScope.process.name;
}
}else{
$location.path("/login");
}
});
$scope.startProcess=function(process){
console.log(process);
$http.post("./startProcess.do",process).success(function(deployResult){
$location.path("/taskList");
});
}
}])
4.对应的填写相关信息的页面:
[html]
view plain copy<center>
<div style="margin-top:20px;margin-left:200px;background-color:#9cc;height:500px;width:50%;font-size:22px;position:relative;float:left;">
<p style="font-size:28px">新建申请</p>
流程定义id:<input type="text" ng-model="process1.proDefId" readonly="readonly" style="background-color:#9dc"/>
</br>
</br>
流程定义key:<input type="text" ng-model="process1.key" readonly="readonly" style="background-color:#9dc"/>
</br>
</br>
申请类型:<input type="text" ng-model="process1.name" readonly="readonly" style="background-color:#9dc"/>
</br>
</br>
申请人:<input type="text" ng-model="process1.appPerson" />
</br>
</br>
申请原因:<input type="text" ng-model="process1.cause"/>
</br>
</br>
申请内容:<input type="text" ng-model="process1.content"/>
</br>
</br>
受理人:<input type="text" ng-model="process1.proPerson"/>
</br>
</br>
<input style="font-size:24px;cursor:pointer" type="button" value="提交申请" ng-click="startProcess(process1);">
<input style="font-size:24px;cursor:pointer" type="button" value="返回">
</div>
</center>
5.成功启动一个流程实例后,会看到act_ru_execution、act_ru_identitylink、act_ru_task、act_ru_variable以及act_hi_actinst、act_hi_detail、act_hi_indentitylink、act_hi_procinst、act_hi_taskinst、act_hi_varinst表中都有了数据。除开variable和varinst中的数据条数是根据对应的流程变量多少来定的,其他都是增加了一条数据。