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

来源:互联网 发布:强制起床闹钟软件 编辑:程序博客网 时间:2024/05/30 04:30
整合在线流程图设计器及遇到的问题(三)
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);@Autowiredprivate 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>

比较匆忙,以后再补充吧!






原创粉丝点击