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

整合在线流程图设计器及遇到的问题(三)
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>

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






  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值