记录一次springboot 整合 activiti的简易流程
maven依赖
activiti自带的mybatis会和你自己的mybatis冲突。在pom文件中加入,取消冲突
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
<!-- activiti -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>5.22.0</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Activiti 流程图 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-diagram-rest</artifactId>
<version>5.22.0</version>
</dependency>
<!-- Activiti 在线设计 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>5.22.0</version>
</dependency>
yml配置
# activiti配置
activiti:
history-level: full
db-history-used: true
database-schema-update: true # 自动部署验证设置:true-开启(默认)、false-关闭
#关闭activiti自动部署(因为我们使用流程设计器部署,不使用具体文件访问方式)
check-process-definitions: true #关闭验证自动部署
async-executor-activate: false
工作流程的绘制
activiti自带的流程绘制工具,在activiti7后官方不在维护。所以用activiti7可能无法在使用。
流程图绘制需要下载activiti5.22的源码包
在项目中导入
其中的editor-app就是编辑器,modeler.html是编辑器的入口页面。
diagram-viewer是流程跟踪插件
还有一个界面组件文件stencilset.json,通过替换它来达到汉化的效果.
Activiti模板绘制类,用来绘制流程图
@RestController
@RequestMapping("model")
@CrossOrigin
public class ActivitiModelController {
@Autowired
private RepositoryService repositoryService;
@Autowired
private IProcesService iProcesService;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private IFlowInfoService flowInfoService;
@Autowired
private ManagementService managementService;
/**
* 新建流程
*
* @param request
* @param response
*/
@RequestMapping("/createModel")
public void createModel(HttpServletRequest request, HttpServletResponse response) {
try {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
Model modelData = repositoryService.newModel();
String name = "LC_PP_TEST";
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "description");
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName(name);
modelData.setKey(StringUtils.defaultString("key"));
repositoryService.saveModel(modelData);
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
request.setAttribute("modelId", modelData.getId());
response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelData.getId());
} catch (Exception e) {
//log.error(e.getMessage(), e);
}
}
/**
* 流程列表查询
*
* @return
*/
@RequestMapping("queryModelList")
public ResponseTableResult queryModelList(HttpServletRequest request) {
int pageNo = Integer.valueOf(request.getParameter("page"));
int pageSize = Integer.valueOf(request.getParameter("limit"));
int firstResult = (pageNo - 1) * pageSize;
long count = repositoryService.createModelQuery().count();
List<Model> list = repositoryService.createModelQuery().orderByCreateTime().desc().listPage(firstResult, pageSize);
return ResponseUtil.makeTableRsp(0, count, list);
}
@PutMapping(value = {"/{modelId}/save"})
@ResponseStatus(HttpStatus.OK)
public void saveModel(@PathVariable String modelId, @RequestParam("name") String name,
@RequestParam("json_xml") String json_xml, @RequestParam("svg_xml") String svg_xml,
@RequestParam("description") String description) {
try {
Model model = this.repositoryService.getModel(modelId);
ObjectNode modelJson = (ObjectNode) this.objectMapper.readTree(model.getMetaInfo());
modelJson.put("name", name);
modelJson.put("description", description);
model.setMetaInfo(modelJson.toString());
model.setName(name);
this.repositoryService.saveModel(model);
this.repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8"));
InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8"));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
transcoder.transcode(input, output);
byte[] result = outStream.toByteArray();
this.repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (Exception e) {
throw new ActivitiException("Error saving model", e);
}
}
/**
* 部署流程
*
* @param request
* @param redirectAttributes
* @return
* @throws IOException
*/
@RequestMapping(value = "deployModel")
public ResponseResult deployModel(HttpServletRequest request, RedirectAttributes redirectAttributes) throws IOException {
String modelId = request.getParameter("modelId");
if (StringUtils.isNoneBlank(modelId)) {
Model modelData = this.repositoryService.getModel(modelId);
ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
byte[] bpmnBytes = null;
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes, "utf-8")).deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
redirectAttributes.addFlashAttribute("message", "部署成功,部署ID=" + deployment.getId());
//向流程定义表保存数据
FlowDef flowDef = new FlowDef();
List<Process> processes = model.getProcesses();
for (Process process : processes) {
flowDef.setFlowCode(process.getId());
flowDef.setFlowName(process.getName());
}
flowInfoService.insertFlowDef(flowDef);
//return ResponseUtil.makeOKRsp("部署成功");
return new ResponseResult(200, "部署成功", null);
}
return new ResponseResult(-200, "系统异常,流程ID不存在", null);
//return ResponseUtil.makeErrRsp(ResultCode.NOT_FOUND.code,"系统异常,流程ID不存在");
}
/**
* 删除流程
*
* @param request
* @return
*/
@RequestMapping("delModel")
public ResponseResult delModel(HttpServletRequest request) {
String modelId = request.getParameter("modelId");
if (StrUtil.isBlank(modelId)) {
return new ResponseResult(ResultCode.ALL_DELETE_ERROR, "流程id不存在");
// return ResponseUtil.makeErrRsp(ResultCode.NOT_FOUND.code,"流程ID不存在!");
}
repositoryService.deleteModel(modelId);
return new ResponseResult(ResultCode.ALL_DELETE_SUCCESS);
//return ResponseUtil.makeOKRsp("删除流程成功!");
}
/**
* 启动流程
*
* @param request
* @return
*/
@RequestMapping("startProcess")
public ResponseResult startProcess(HttpServletRequest request) {
String vacationId = request.getParameter("vacationId");
flowInfoService.resolve(Long.valueOf(vacationId), null);
return new ResponseResult(ResultCode.AAL_LAYUI_SUCCESS);
//return ResponseUtil.makeOKRsp();
}
/**
* 流程图查询
*
* @param request
*/
@RequestMapping("queryFlowImg")
public void queryFlowImg(HttpServletRequest request, HttpServletResponse response) throws IOException {
String flowId = request.getParameter("flowId");
InputStream inputStream = null;
if (StrUtil.isBlank(flowId) || StrUtil.equals("null", flowId)) {
inputStream = this.getClass().getClassLoader().getResourceAsStream("static/images/no_flowInfo.png");
} else {
Command<InputStream> cmd = new HistoryProcessInstanceDiagramCmd(flowId);
inputStream = managementService.executeCommand(cmd);
}
BufferedOutputStream bout = new BufferedOutputStream(response.getOutputStream());
try {
if (null == inputStream) {
inputStream = this.getClass().getResourceAsStream("/images/no_flowInfo.png");
}
byte b[] = new byte[1024];
int len = inputStream.read(b);
while (len > 0) {
bout.write(b, 0, len);
len = inputStream.read(b);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
bout.close();
if (null != inputStream) {
inputStream.close();
}
}
}
}
springboot主启动类
主启动类需要加入下方注解,如果不加。会报错。
@SpringBootApplication(exclude = {LiquibaseAutoConfiguration.class,
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class,
SecurityAutoConfiguration.class})
@MapperScan("com.it.*.mapper")
public class BeautyAdmin {
public static void main(String[] args) {
SpringApplication.run(BeautyAdmin.class, args);
}
}
在项目中,导入下方三个controlelr
**
* @author Tijs Rademakers
*/
@RestController
@RequestMapping("/service")
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getEditorJson(@PathVariable String modelId) {
ObjectNode modelNode = null;
Model model = repositoryService.getModel(modelId);
if (model != null) {
try {
if (StringUtils.isNotEmpty(model.getMetaInfo())) {
modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
} else {
modelNode = objectMapper.createObjectNode();
modelNode.put(MODEL_NAME, model.getName());
}
modelNode.put(MODEL_ID, model.getId());
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
modelNode.put("model", editorJsonNode);
} catch (Exception e) {
LOGGER.error("Error creating model JSON", e);
throw new ActivitiException("Error creating model JSON", e);
}
}
return modelNode;
}
}
@RestController
@RequestMapping(value = "/service")
public class ModelSaveRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.OK)
public void saveModel(@PathVariable String modelId, @RequestParam("name") String name,
@RequestParam("json_xml") String json_xml,
@RequestParam("svg_xml") String svg_xml,
@RequestParam("description") String description) {//对接收参数进行了修改
try {
Model model = repositoryService.getModel(modelId);
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
modelJson.put(MODEL_NAME, name);
modelJson.put(MODEL_DESCRIPTION, description);
model.setMetaInfo(modelJson.toString());
model.setName(name);
repositoryService.saveModel(model);
repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8"));
InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8"));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
// Setup output
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (Exception e) {
LOGGER.error("Error saving model", e);
throw new ActivitiException("Error saving model", e);
}
}
}
/**
* @author Tijs Rademakers
*/
@RestController
@RequestMapping("/service")
public class StencilsetRestResource {
@RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
public @ResponseBody
String getStencilset() {
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
try {
return IOUtils.toString(stencilsetStream, "utf-8");
} catch (Exception e) {
throw new ActivitiException("Error while loading stencil set", e);
}
}
}