前言:我们在开发类似审批,请假,常常要很多流,如果按照写代码的方式那逻辑,代码量就多了,所以我们可以用有些工作流框架来实现,像activity和Camunda等工作流框架来实现。

一:Springboot集成activity工作流的实现

1.先要在pom.xml加入依赖,我们可以看到集成了activity,engine,modeler等基础依赖

<dependencies>
<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>
<version>1.9.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!--activiti begin-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>

<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>

<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>${activiti.version}</version>
</dependency>

<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-diagram-rest</artifactId>
<version>${activiti.version}</version>
</dependency>

2.写一些有关activity自动建表和实现代码

一:有些公有配置项

1> ActivityConfig.java

@Configuration
public class ActivityConfig {

//流程配置,与spring整合采用SpringProcessEngineConfiguration这个实现
@Bean
public ProcessEngineConfiguration processEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager){
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
processEngineConfiguration.setDataSource(dataSource);
processEngineConfiguration.setDatabaseSchemaUpdate("true");
processEngineConfiguration.setDatabaseType("mysql");

processEngineConfiguration.setTransactionManager(transactionManager);

//流程图字体
processEngineConfiguration.setActivityFontName("宋体");
processEngineConfiguration.setAnnotationFontName("宋体");
processEngineConfiguration.setLabelFontName("宋体");

return processEngineConfiguration;
}

//流程引擎,与spring整合使用factoryBean
@Bean
public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration){
ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
return processEngineFactoryBean;
}

//八大接口
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine){
return processEngine.getRepositoryService();
}

@Bean
public RuntimeService runtimeService(ProcessEngine processEngine){
return processEngine.getRuntimeService();
}

@Bean
public TaskService taskService(ProcessEngine processEngine){
return processEngine.getTaskService();
}

@Bean
public HistoryService historyService(ProcessEngine processEngine){
return processEngine.getHistoryService();
}

@Bean
public FormService formService(ProcessEngine processEngine){
return processEngine.getFormService();
}

@Bean
public IdentityService identityService(ProcessEngine processEngine){
return processEngine.getIdentityService();
}

@Bean
public ManagementService managementService(ProcessEngine processEngine){
return processEngine.getManagementService();
}

@Bean
public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine){
return processEngine.getDynamicBpmnService();
}

//八大接口 end
}

2> UtilConfig.java

@Configuration
public class UtilConfig {


//jackson xml util
@Bean
public ObjectMapper objectMapper(){
return new ObjectMapper();
}
}

3> ViewConfig

@Configuration
public class ViewConfig extends WebMvcConfigurerAdapter {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("/index.html");
}
}

二:模型管理项

1> DeploymentController

/**
* 模型管理
*/
@RestController
@RequestMapping("models")
public class ModelerController implements RestServiceController<Model, String> {

@Autowired
RepositoryService repositoryService;
@Autowired
ObjectMapper objectMapper;

/**
* 新建一个空模型
* @return
* @throws UnsupportedEncodingException
*/
@PostMapping("newModel")
public Object newModel() throws UnsupportedEncodingException {
//初始化一个空模型
Model model = repositoryService.newModel();

//设置一些默认信息
String name = "new-process";
String description = "";
int revision = 1;
String key = "process";

ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

model.setName(name);
model.setKey(key);
model.setMetaInfo(modelNode.toString());

repositoryService.saveModel(model);
String id = model.getId();

//完善ModelEditorSource
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);
repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
return ToWeb.buildResult().redirectUrl("/editor?modelId="+id);
}


/**
* 发布模型为流程定义
* @param id
* @return
* @throws Exception
*/
@PostMapping("{id}/deployment")
public Object deploy(@PathVariable("id")String id) throws Exception {

//获取模型
Model modelData = repositoryService.getModel(id);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

if (bytes == null) {
return ToWeb.buildResult().status(Status.FAIL)
.msg("模型数据为空,请先设计流程并成功保存,再进行发布。");
}

JsonNode modelNode = new ObjectMapper().readTree(bytes);

BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if(model.getProcesses().size()==0){
return ToWeb.buildResult().status(Status.FAIL)
.msg("数据模型不符要求,请至少设计一条主线流程。");
}
byte[] 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);

return ToWeb.buildResult().refresh();
}

@Override
public Object getOne(@PathVariable("id") String id) {
Model model = repositoryService.createModelQuery().modelId(id).singleResult();
return ToWeb.buildResult().setObjData(model);
}

@Override
public Object getList(@RequestParam(value = "rowSize", defaultValue = "1000", required = false) Integer rowSize, @RequestParam(value = "page", defaultValue = "1", required = false) Integer page) {
List<Model> list = repositoryService.createModelQuery().listPage(rowSize * (page - 1)
, rowSize);
long count = repositoryService.createModelQuery().count();

return ToWeb.buildResult().setRows(
ToWeb.Rows.buildRows().setCurrent(page)
.setTotalPages((int) (count/rowSize+1))
.setTotalRows(count)
.setList(list)
.setRowSize(rowSize)
);
}

public Object deleteOne(@PathVariable("id")String id){
repositoryService.deleteModel(id);
return ToWeb.buildResult().refresh();
}

@Override
public Object postOne(@RequestBody Model entity) {
throw new UnsupportedOperationException();
}

@Override
public Object putOne(@PathVariable("id") String s, @RequestBody Model entity) {
throw new UnsupportedOperationException();
}

@Override
public Object patchOne(@PathVariable("id") String s, @RequestBody Model entity) {
throw new UnsupportedOperationException();
}


}

三:保存或者修改模型项

1> ModelSaveRestResource

@RestController
@RequestMapping("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);
}
}

2> ModelEditorJsonRestResource

@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;
}
}

四:当然还有前端代码,我就不一一介绍啦

启动之后:访问​​http://localhost:8089/model-list.html​

1> 流程图绘制

Springboot+activity5.22.0工作流集成并且集成视图模型_spring


Springboot+activity5.22.0工作流集成并且集成视图模型_html_02

2> 保存流程图

Springboot+activity5.22.0工作流集成并且集成视图模型_html_03

Springboot+activity5.22.0工作流集成并且集成视图模型_spring_04

3> 发布流程

Springboot+activity5.22.0工作流集成并且集成视图模型_ide_05

工作流在做管理系统会比较常用