定义
<groupId>com.zhun</groupId>
<artifactId>activiti-editor</artifactId>
<version>0.0.1-SNAPSHOT</version>
继承
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
依赖
<properties>
<java.version>1.8</java.version>
<activiti.version>5.22.0</activiti.version>
<!-- 数据库 Start -->
<spring-boot-alibaba-druid.version>1.1.16</spring-boot-alibaba-druid.version>
<mysql-connector.version>8.0.15</mysql-connector.version>
<!-- 数据库 End -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- web相关 Start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!-- web相关 End-->
<!-- 数据库 Start -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${spring-boot-alibaba-druid.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!-- 数据库 End -->
<!-- Activiti Start -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-actuator</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-explorer</artifactId>
<version>${activiti.version}</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
</exclusion>
<exclusion>
<groupId>org.vaadin.addons</groupId>
<artifactId>dcharts-widget</artifactId>
</exclusion>
<exclusion>
<groupId>activiti-simple-workflow</groupId>
<artifactId>org.activiti</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Activiti End -->
<!-- 工具 Start -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
<!-- 工具 End -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
配置文件application.yml
server:
port: 8080
servlet:
context-path:
spring:
datasource:
druid:
url: jdbc:mysql://127.0.0.1:3306/activiti5?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
driver-class-name: com.mysql.cj.jdbc.Driver
# activiti相关配置
activiti:
check-process-definitions: false #自动检查、部署流程定义文件
database-schema-update: true #自动更新数据库结构
process-definition-location-prefix: classpath:/processes/bpmn/ #流程定义文件存放目录
#process-definition-location-suffixes: #流程文件格式
# - **.bpmn20.xml
# - **.bpmn
#保存历史数据级别设置为full最高级别,便于历史数据的追溯
history-level: full
async-executor-activate: false
#禁用activiti自带用户与用户组相关表(共计4张表,禁用后剩24张表)
db-identity-used: true
#禁用activiti历史表(共计8张表,禁用后剩下20张表)
#db-history-used: false
rest-api-enabled: true
thymeleaf:
cache: false
mode: HTML5
encoding: UTF-8
servlet:
content-type: text/html
mybatis-plus:
configuration:
call-setters-on-nulls: true
map-underscore-to-camel-case: true
- 自行创建数据库activiti5
- 自行创建数据库表
接口源码
StencilsetRestResource
@RestController
@RequestMapping(value = "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);
}
}
}
ModelEditorJsonRestResource
@RestController
@RequestMapping(value = "/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;
}
}
ModelSaveRestResource
@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,
String name, String description, String json_xml, String svg_xml) {
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);
// Do the transformation
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);
}
}
}
扩展接口
@Controller
public class IndexController {
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@GetMapping({"", "index"})
public String index(ModelMap modelMap) {
modelMap.put("modelList", repositoryService.createModelQuery().list());
return "index";
}
@GetMapping("modeler")
public String modeler() {
return "modeler";
}
/**
* 创建模型
*
* @param response
* @param name 模型名称
* @param key 模型key
*/
@RequestMapping(value = "/create",method = RequestMethod.GET)
public void create(HttpServletResponse response, String name, String key) throws IOException {
logger.info("创建模型入参name:{},key:{}", name, key);
Model model = repositoryService.newModel();
ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "");
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
model.setName(name);
model.setKey(key);
model.setMetaInfo(modelNode.toString());
repositoryService.saveModel(model);
createObjectNode(model.getId());
response.sendRedirect("/modeler?modelId=" + model.getId());
logger.info("创建模型结束,返回模型ID:{}", model.getId());
}
/**
* 创建模型时完善ModelEditorSource
*
* @param modelId
*/
@SuppressWarnings("deprecation")
private void createObjectNode(String modelId) {
logger.info("创建模型完善ModelEditorSource入参模型ID:{}", modelId);
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);
try {
repositoryService.addModelEditorSource(modelId, editorNode.toString().getBytes("utf-8"));
} catch (Exception e) {
logger.info("创建模型时完善ModelEditorSource服务异常:{}", e);
}
logger.info("创建模型完善ModelEditorSource结束");
}
}
设计器源码复制
- resources/static/diagram-viewer
- resources/static/editor-app
- resources/stencilset.json
- resources/templates/modeler.html
- resources/tempaltes/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Activiti 5.22 设计器</title>
</head>
<body>
<h2>
<a href='/create?name=activiti&key=123456'>绘制流程</a>
</h2>
<div>
<table width="100%">
<tr>
<td width="10%">模型编号</td>
<td width="10%">版本</td>
<td width="20%">模型名称</td>
<td width="20%">模型key</td>
<td width="40%">操作</td>
</tr>
<tr th:each="model:${modelList}">
<td width="10%" th:text="${model.id}"></td>
<td width="10%" th:text="${model.version}"></td>
<td width="20%" th:text="${model.name}"></td>
<td width="20%" th:text="${model.key}"></td>
<td width="40%">
<a th:href="|/modeler?modelId=${model.id}|">编辑</a>
<a th:href="|/publish?modelId=${model.id}|">发布</a>
<a th:href="|/revokePublish?modelId=${model.id}|">撤销</a>
<a th:href="|/delete?modelId=${model.id}|">删除</a>
</td>
</tr>
</table>
</div>
</body>
</html>
访问
http://localhost:8080
码云地址
https://gitee.com/piaoyi95/acticiti-editor