您的位置:首页 > 其它

整合在线流程图设计器及遇到的问题(三)

2017-07-31 12:01 281 查看
整合在线流程图设计器及遇到的问题(三)
1.整合注意事项:
    在整合之前先要确定你的项目spring版本是否为4.0+,如果不是就麻烦些了,因为activiti modeler设计器需要用到rest风格即RestControl注解,如果是低版本的,那么我猜想需要将这部分代码单独拿出来进行处理,不过我没有做过,这点需要注意了。

2.开始整合:
直接下载给的项目(maven版本的),
链接:http://download.csdn.net/detail/qq_27063119/9916164
打开activiti项目,复制editor-app目录至项目的webapp下,将modeler.html拷至webapp目录下,将stencilset.json拷贝至resource目录下,spring MVC配置中加入:
<!--加入Spring Activiti-Modeler的运行配置 -->
<context:component-scan base-package="org.activiti.rest.editor.*"/>
<context:component-scan base-package="org.activiti.rest.common.*"/>


最后还有一个地方,如果你的项目名不是activiti的,需要打开editor-app -> app-cfg.js,将
var ACTIVITI = ACTIVITI || {};

ACTIVITI.CONFIG = {
'contextRoot' : '/activiti/service',
};

activiti 修改为你的项目名即可,这里整合就结束了,是不是非常之快!
activiti项目中已经给了创建modeler并且跳转至流程编辑页面的controller

@Controller
@RequestMapping("/model")
public class ModuleController {

private Logger logger = LoggerFactory.getLogger(ModuleController.class);

@Autowired
private RepositoryService repositoryService;

@RequestMapping(value = "create")
public void create(@RequestParam("name") String name, @RequestParam("key") String key, @RequestParam("description") String description,
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();

ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
description = StringUtils.defaultString(description);
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"));

response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelData.getId());
} catch (Exception e) {
logger.error("创建模型失败:", e);
}
}
}


项目访问地址为: http://IP地址:端口号/项目名/model/create?name=test&key=test&description=testModel
3.遇到的问题以及解决办法:

(1)流程图中文错误乱码问题

通过activiti modeler画好流程图保存后,发现生成的流程图片中文显示乱码,或者不显示,
这是由于缺少字体的原因:
向activiti的配置文件中(spring-activiti.xml)加入字体配置即可:

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="myDataSource" />
<!-- 配置事务管理器,统一事务 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 设置建表策略,如果没有表,自动创建表 -->
<property name="databaseSchemaUpdate" value="true" />

<!-- 用于更改流程节点的执行行为 -->
<property name="activityBehaviorFactory" ref="activityBehaviorFactoryExt"/>

<!-- 生成流程图的字体   解决图片中文不显示问题-->
<property name="activityFontName" value="宋体"></property>
<property name="labelFontName" value="宋体"></property>
</bean>

(2)流程部署的时候,发生错误:
java.lang.NoSuchMethodError: org.apache.commons.collections.CollectionUtils.isNotEmpty(Ljava/util/Collection;)Z

这是由于common.jar冲突了,activiti也会引入该jar,如果你的项目之前引入过不同版本的该jar,那么部署流程的时候就会发生该错误。

(3)生成流程图片时,分支条件名不显示的问题

下载源码activiti-image-generator,修改org.activiti.image.impl.DefaultProcessDiagramGenerator.java 大概655行左右:
原代码为:
if (labelGraphicInfo != null) {
processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false);
}
修改为:
//2017-7-27 @yn 针对解决流程设计器绘图   生成图片分支条件不显示问题
if (labelGraphicInfo != null) { processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false); }else{
GraphicInfo lineCenter = getLineCenter(graphicInfoList);
processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false);
}


如果需要更改分支条件名的字体那么需要修改org.activiti.image.impl.DefaultProcessDiagramCanvas.java 大概219行左右,原代码为:
LABEL_FONT = new Font(labelFontName, Font.ITALIC, 10);
修改为:
//2017-7-27  @yn 修改流程分支条件字体样式
LABEL_FONT = new Font(labelFontName, Font.BOLD, 14);
编译好后,替换至jar中,即可,更新pom,刷新依赖包即可

(4)如何自定义表达式解析器

加入三个类:
扩展缺省的流程节点默认工厂类 ActivityBehaviorFactoryExt.java
import javax.annotation.Resource;

import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
import org.springframework.stereotype.Component;

/**
* @author nuohy
* @Description: 扩展缺省的流程节点默认工厂类,实现对Activiti节点的执行的默认行为的更改
* @date 2017年7月22日
*/
@Component(value="activityBehaviorFactoryExt")
public class ActivityBehaviorFactoryExt extends DefaultActivityBehaviorFactory {

@Resource(name="exclusiveGatewayActivityBehaviorExt")
private ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt;

/**
* 通过Spring容器注入新的分支条件行为执行类
*/
public void setExclusiveGatewayActivityBehaviorExt(ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt) {
this.exclusiveGatewayActivityBehaviorExt = exclusiveGatewayActivityBehaviorExt;
}

/**
* 重写父类中的分支条件行为执行类
*/
@Override
public ExclusiveGatewayActivityBehavior createExclusiveGatewayActivityBehavior(ExclusiveGateway exclusiveGateway) {
return exclusiveGatewayActivityBehaviorExt;
}
}


对网关的条件判断类,ExclusiveGatewayActivityBehaviorExt.java
import java.util.List;

import javax.annotation.Resource;
import javax.script.ScriptException;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.Condition;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.springframework.stereotype.Component;

/**
*
* @author nuohy
* @Description: 对网关的条件判断,优先使用扩展的配置
* @date 2017年7月22日
*/
@Component(value="exclusiveGatewayActivityBehaviorExt")
@SuppressWarnings("serial")
public class ExclusiveGatewayActivityBehaviorExt extends ExclusiveGatewayActivityBehavior{

//解析脚本
@Resource(name="conditionAnalysis")
private ActivitiConditionAnalysis conditionAnalysis;

@Override
protected void leave(ActivityExecution execution) {

PvmTransition outgoingSeqFlow = null;
String defaultSequenceFlow = (String) execution.getActivity().getProperty("default");
List<PvmTransition> list = execution.getActivity().getOutgoingTransitions();

if(outgoingSeqFlow == null&&list!=null&&list.size()>0){
for (PvmTransition seqFlow : list) {
Condition condition = (Condition) seqFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION);

try {
//处理解析 表达式
boolean evaluate = conditionAnalysis.analysis(execution.getVariables(),seqFlow, seqFlow.getId());

if((condition == null && (defaultSequenceFlow == null || !defaultSequenceFlow.equals(seqFlow.getId()))) || evaluate){
outgoingSeqFlow = seqFlow;
}
} catch (ScriptException e) {
e.printStackTrace();
}

//源代码
/*boolean evaluate = (condition != null && condition.evaluate(execution));
if((condition == null && (defaultSequenceFlow == null || !defaultSequenceFlow.equals(seqFlow.getId()))) || evaluate){
outgoingSeqFlow = seqFlow;
}*/

}
}

if (outgoingSeqFlow != null) {
execution.take(outgoingSeqFlow);
} else {
if (defaultSequenceFlow != null) {
PvmTransition defaultTransition = execution.getActivity().findOutgoingTransition(defaultSequenceFlow);
if (defaultTransition != null) {
execution.take(defaultTransition);
} else {
throw new ActivitiException("未发现默认流程线路'" + defaultSequenceFlow );
}
} else {
//No sequence flow could be found, not even a default one
throw new ActivitiException("没有找到网关出口  activiti.id:"+ execution.getActivity().getId() + " 流程不能继续进行!");
}
}

}

}


activiti 条件表达式 解析类,ActivitiConditionAnalysis.java   (具体怎样解析,都在这里面写好实现,这里我用了ScriptEngine引擎)
import java.util.Map;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.activiti.engine.impl.pvm.PvmTransition;
import org.springframework.stereotype.Component;

/**
*
* @author nuohy
* @Description: activiti 条件表达式 解析
* @date 2017年7月22日
*/
@Component(value = "conditionAnalysis")
public class ActivitiConditionAnalysis {

/**
*
* @param Variables - 流程变量
* @param seqFlow	- 分支条件
* @param seqFlowId	- flowid
* @return
* @throws ScriptException
*/
public boolean analysis(Map<String, Object> Variables, PvmTransition seqFlow, String seqFlowId) throws ScriptException {

String conditionText = (String) seqFlow.getProperty("conditionText");

System.out.println("---------------进行一个替换---------------");

//替换${}括号等无效字符
conditionText = conditionText.replaceAll("\\$\\{", "").replaceAll("\\}", "");

//替换变量数值
if (Variables != null && Variables.size() > 0) {
for (String key : Variables.keySet()) {
conditionText = conditionText.replaceAll(key, Variables.get(key).toString());
}
}

//开始boolean 计算
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");

boolean result = (Boolean) scriptEngine.eval(conditionText);

if (result) {
System.out.println("true seqFlowId:" + seqFlowId + "    表达式为:" + conditionText);
}else{
System.out.println("false seqFlowId:" + seqFlowId + "    表达式为:" + conditionText);
}

return result;
}

}


最后需要在spring-activiti.xml中配置一下:
<!-- spring负责创建流程引擎的配置文件 -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="myDataSource" />
<!-- 配置事务管理器,统一事务 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 设置建表策略,如果没有表,自动创建表 -->
<property name="databaseSchemaUpdate" value="true" />

<!-- 用于更改流程节点的执行行为 -->
<property name="activityBehaviorFactory" ref="activityBehaviorFactoryExt"/>

<!-- 生成流程图的字体   解决图片中文不显示问题-->
<property name="activityFontName" value="宋体"></property>
<property name="labelFontName" value="宋体"></property>
</bean>


比较匆忙,以后再补充吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: