瞎整了一个晚上加一个上午,终于整合完成了,记录以便下次使用
Spring boot版本:1.5.3
activiti版本:5.22.0
其中:
首先从官方下载activiti5.22.0版本的全代码包,并在本地解压待用
activiti-webapp-explorer2
中复制src\main\java\org\activiti\explorer\servlet
路径下的文件(图中的A部分)到本地项目中(如启动后无法访问静态资源文件,则删除DispatherServletConfiguration.java这个文件)activiti-webapp-explorer2
中复制src\main\resources
路径下的stencilset.json
文件到本地项目的resources目录下(我这里为了管理放在了resources/activiti/modeler目录下)activiti-webapp-explorer2
中复制src\main\webapp
路径下的文件(图中B部分)到本地项目的resources/public/static目录下activiti-modeler
中复制src\main\java\org\activiti\rest\editor
路径下的文件(图中的C部分)到本地项目中以上拷贝的路径参考上图
为了整合能够达到效果,我们需要对以下文件进行修改
1)修改本地项目的pom.xml
,增加如下依赖
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-spring-boot-starter-basicartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-spring-boot-starter-actuatorartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-restartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.apache.xmlgraphicsgroupId>
<artifactId>batik-codecartifactId>
<version>1.7version>
dependency>
<dependency>
<groupId>org.apache.xmlgraphicsgroupId>
<artifactId>batik-cssartifactId>
<version>1.7version>
dependency>
<dependency>
<groupId>org.apache.xmlgraphicsgroupId>
<artifactId>batik-svg-domartifactId>
<version>1.7version>
dependency>
<dependency>
<groupId>org.apache.xmlgraphicsgroupId>
<artifactId>batik-svggenartifactId>
<version>1.7version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-explorerartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-diagram-restartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-simple-workflowartifactId>
<version>${activiti.version}version>
dependency>
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-springartifactId>
<version>${activiti.version}version>
dependency>
2)修改DispatcherServletConfiguration.java
改为如下:
@Configuration
@ComponentScan({"org.activiti.rest.editor", "org.activiti.rest.diagram"})
public class DispatcherServletConfiguration {
private final Logger log = LoggerFactory.getLogger(DispatcherServletConfiguration.class);
@Bean
public SessionLocaleResolver localeResolver() {
return new SessionLocaleResolver();
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
log.debug("Configuring localeChangeInterceptor");
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("language");
return localeChangeInterceptor;
}
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
log.debug("Creating requestMappingHandlerMapping");
RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
Object[] interceptors = {localeChangeInterceptor()};
requestMappingHandlerMapping.setInterceptors(interceptors);
return requestMappingHandlerMapping;
}
}
3)修改StencilsetRestResource.java
(如果在拷贝stencilset.json
时没有放在resources目录下)
将
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
改为
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("activiti.modeler/stencilset.json");
4)修改StencilsetRestResource.java
、ModelEditorJsonRestResource.java
、ModelSaveRestResource.java
统一在类上加
@RequestMapping(value = "/service")
5)修改Spring boot 启动类Application.java
在里面增加注解
@ComponentScan({"org.activiti.rest.diagram", "com.westcatr.rd"})
@EnableAsync
同时增加一个filter
@Bean
public JsonpCallbackFilter filter(){
return new JsonpCallbackFilter();
}
6)修改editor-app
下的app-cfg.js
,将
ACTIVITI.CONFIG = {
'contextRoot' : 'activiti-webapp-explorer2/service',
};
改为
ACTIVITI.CONFIG = {
'contextRoot' : '/service',
};
7)修改ModelSaveRestResource.java
(主要是因为集成后保存时候报400错误)
将代码改为如下
@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);
// 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);
}
}
}
8)修改activiti-modeler
编辑关闭时返回的路径
整合完成后,启动项目,访问http://localhost:8080/static/modeler.html?modelId=1
我们可以看到一个空白的编辑器,里面什么也木有。原因是什么呢,是因为我们的modelId=1是乱输入的,他应该要和数据库表ACT_RE_MODEL
对应起来才对。那么这张表里的数据如何来的呢,我们需要自己写一个Controller,对应封装4个方法:1.新建一个空的模型;2.所有模型列表;3.发布模型;4.删除模型;(activiti已提供了保存修改和获取模型节点信息的方法,就是上面C部分的那3个类)
参考代码(该部分代码感谢:http://www.jianshu.com/p/cf766a713a86)
@RestController
@RequestMapping("models")
public class ModelerController {
@Autowired
ProcessEngine processEngine;
@Autowired
ObjectMapper objectMapper;
/**
* 新建一个空模型
* @return
* @throws UnsupportedEncodingException
*/
@PostMapping
public Object newModel() throws UnsupportedEncodingException {
RepositoryService repositoryService = processEngine.getRepositoryService();
//初始化一个空模型
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("/modeler.html?modelId="+id);
}
/**
* 获取所有模型
* @return
*/
@GetMapping
public Object modelList(){
RepositoryService repositoryService = processEngine.getRepositoryService();
List models = repositoryService.createModelQuery().list();
return ToWeb.buildResult().putData("models", models);
}
/**
* 删除模型
* @param id
* @return
*/
@DeleteMapping("{id}")
public Object deleteModel(@PathVariable("id")String id){
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.deleteModel(id);
return ToWeb.buildResult().refresh();
}
/**
* 发布模型为流程定义
* @param id
* @return
* @throws Exception
*/
@PostMapping("{id}/deployment")
public Object deploy(@PathVariable("id")String id) throws Exception {
//获取模型
RepositoryService repositoryService = processEngine.getRepositoryService();
Model modelData = repositoryService.getModel(id);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
return ToWeb.buildResult().status(Config.FAIL)
.msg("模型数据为空,请先设计流程并成功保存,再进行发布。");
}
JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if(model.getProcesses().size()==0){
return ToWeb.buildResult().status(Config.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();
}
}
我们经常会使用其他的工具来制作bpmn文件,如使用eclipse的activiti designer,在我们的项目集成好activiti modeler后,就不需要再用其他工具来编辑了。那么如何将现有的bpmn文件导入到继承好的activiti modeler里呢。
通过对源码的查看,可以从activiti-exporer
中的ImportUploadReceiver.java
里找到一些思路,我们可以新建一个上传方法,即可上传我们的现有bpmn文件。代码如下:
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public void deployUploadedFile(
@RequestParam("uploadfile") MultipartFile uploadfile) {
InputStreamReader in = null;
try {
try {
boolean validFile = false;
String fileName = uploadfile.getOriginalFilename();
if (fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn")) {
validFile = true;
XMLInputFactory xif = XmlUtil.createSafeXmlInputFactory();
in = new InputStreamReader(new ByteArrayInputStream(uploadfile.getBytes()), "UTF-8");
XMLStreamReader xtr = xif.createXMLStreamReader(in);
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
if (bpmnModel.getMainProcess() == null || bpmnModel.getMainProcess().getId() == null) {
// notificationManager.showErrorNotification(Messages.MODEL_IMPORT_FAILED,
// i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_BPMN_EXPLANATION));
System.out.println("err1");
} else {
if (bpmnModel.getLocationMap().isEmpty()) {
// notificationManager.showErrorNotification(Messages.MODEL_IMPORT_INVALID_BPMNDI,
// i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_BPMNDI_EXPLANATION));
System.out.println("err2");
} else {
String processName = null;
if (StringUtils.isNotEmpty(bpmnModel.getMainProcess().getName())) {
processName = bpmnModel.getMainProcess().getName();
} else {
processName = bpmnModel.getMainProcess().getId();
}
Model modelData;
modelData = repositoryService.newModel();
ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processName);
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName(processName);
repositoryService.saveModel(modelData);
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
ObjectNode editorNode = jsonConverter.convertToJson(bpmnModel);
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
}
}
} else {
// notificationManager.showErrorNotification(Messages.MODEL_IMPORT_INVALID_FILE,
// i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_FILE_EXPLANATION));
System.out.println("err3");
}
} catch (Exception e) {
String errorMsg = e.getMessage().replace(System.getProperty("line.separator"), "
");
// notificationManager.showErrorNotification(Messages.MODEL_IMPORT_FAILED, errorMsg);
System.out.println("err4");
}
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// notificationManager.showErrorNotification("Server-side error", e.getMessage());
System.out.println("err5");
}
}
}
}
补充:上面的是之前做项目整合时的流程记录,看到有朋友说不能够整合,今天按照流程重新整合了一遍,并上传了代码,传送门:http://download.csdn.net/detail/chenhai201/9862887