背景:在SPRING 框架之中, 有一个服务端需要提供多种形态的服务,这里的多种形态只是返回值得展示形式(其实 数据内在逻辑完全一样), 比如:
形式1: JSONP({“key1”: value1, "key2":value2, "key3":value3, })
形式2: {“key1”: value1, "key2":value2, "key3":value3, }
为了使得后台业务处理代码一样(不做任何区分),现在理由过滤器,对返回接口进行处理,根据需要加上 :JSONP()
主要实现步骤如下:
1 在webxml 中配置过滤器
<filter>
<filter-name>RewriteResponse</filter-name>
<filter-class>comrobinfilterRewriteResponse</filter-class>
</filter>
<filter-mapping>
<filter-name>RewriteResponse</filter-name>
<servlet-name>/</servlet-name>
</filter-mapping>
// 斜杠星代表匹配任何请求
2 重点在于RewriteResponse 过滤器
public class RewriteResponseFilter extends Filter {
public String description() {
// TODO Auto-generated method stub
return null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException {
// TODO Auto-generated method stub
ResponseWrapper responseWrapper = new ResponseWrapper((>
Activiti的流程分支条件目前是采用脚本判断方式,并且需要在流程定义中进行分支条件的设定,如下图所示:
${input == 1}
${input == 2}
${input == 3}
从上面的定义可以看到,流程的分支条件存在以下两个致命的局限性:
1.分支条件需要在流程定义(XML)中设定,这要求流程定义必须由开发人员来设计及编写
2.分支条件比较简单,一般为boolean表达式,表达式里的为单变量的判断处理。
以上两个局限性限制了流程的分支判断处理必须由开发人员来设定,而国内的大部分的流程应用都要求是普通的业务人员即可处理,或者是由有一定计算机基础的人员来设置处理。这要求我们对流程的条件设置提出了更高的要求,上一节我们通过修改Activiti的流程定义的XML中的分支条件表达式,同时刷新流程定义的引擎缓存,如下的代码就是基于这种方式:
JsonNode jsonObject=objectMapperreadTree(configJson);
JsonNode configsNode=jsonObjectget("configs");
BpmSolution bpmSolution=bpmSolutionManagerget(solId);
BpmDef bpmDef=bpmDefManagergetLatestBpmByKey(bpmSolutiongetDefKey(), ContextUtilgetCurrentTenantId());
ActProcessDef processDef=actRepServicegetProcessDef(bpmDefgetActDefId());
String processDefXml=actRepServicegetBpmnXmlByDeployId(bpmDefgetActDepId());
Systemoutprintln("xml:"+processDefXml);
ActNodeDef sourceNode=processDefgetNodesMap()get(nodeId);
ByteArrayInputStream is=new ByteArrayInputStream(processDefXmlgetBytes());
Map map = new HashMap();
mapput("bpm","");
mapput("xsi","");
SAXReader saxReader = new SAXReader();
saxReadergetDocumentFactory()setXPathNamespaceURIs(map);
Document doc = saxReaderread(is);
//Document doc=Dom4jUtilload(is, "UTF-8");
Element rootEl=docgetRootElement();
if(configsNode!=null){
//取得分支条件列表
JsonNode configs=configsNodeget("conditions");
if(configs!=null){
Iterator it=configselements();
while(ithasNext()){
ObjectNode config=(ObjectNode)itnext();
String tmpNodeId=configget("nodeId")textValue();
String tmpCondition=configget("condition")textValue();
Element seqFlow=(Element)rootElselectSingleNode("/bpm:definitions/bpm:process/bpm:sequenceFlow[@sourceRef='"
+sourceNodegetNodeId()+"' and @targetRef='"+tmpNodeId+"']");
if(seqFlow==null) continue;
Element conditionExpress=(Element)seqFlowselectSingleNode("bpm:conditionExpression");
if(conditionExpress==null){
conditionExpress=seqFlowaddElement("conditionExpression");
conditionExpressaddAttribute("xsi:type", "tFormalExpression");
}else{
conditionExpressclearContent();
}
conditionExpressaddCDATA(tmpCondition);
}
}
}
//修改流程定义的XML,并且清空该流程定义的缓存
actRepServicedoModifyXmlAndClearCache(bpmDefgetActDefId(),bpmDefgetActDepId(), docasXML());
说明
1.基于这种方式容易出错,因为流程的分支条件写回流程定义的XML是比较容易出问题的,同时不清楚人员填写什么条件回XML文件中。
2.对于Jsaas中的一个流程定义可用于多个流程解决方案中使用配置不同的条件不太适合,因为一个流程定义是一样,但可能会分支的条件设置不一样。
基于以上的要求,为此我们对Activiti进行扩展,以使得我们可以允许流程引擎在分支判断处理中,执行我们的条件设置,其原理如下:
当流程引擎跳至分支条件判断处理时,可以让它执行我们的脚本设置条件,条件满足时,则跳至我们的设置的目标节点,从而实现干预流程引擎本身的执行方式,为了不影响Activiti的原的运行机制,我们还是保留其旧的执行判断方式。
二、Activiti的扩展点
Activiti的流程扩展是比较灵活的,我们通过改写这个ExclusiveGateway的节点的行为方法即可,其实现方法如下:
package comredxunbpmactivitiext;
import javautilIterator;
import javaxannotationResource;
import orgactivitiengineimplbpmnbehaviorExclusiveGatewayActivityBehavior;
import orgactivitiengineimplpvmPvmTransition;
import orgactivitiengineimplpvmdelegateActivityExecution;
import orgapachecommonslangStringUtils;
import orgslf4jLogger;
import orgslf4jLoggerFactory;
import comredxunbpmcoreentityconfigExclusiveGatewayConfig;
import comredxunbpmcoreentityconfigNodeExecuteScript;
import comredxunbpmcoremanagerBpmNodeSetManager;
import comredxuncorescriptGroovyEngine;
import comsunstarunoRuntimeException;
/
对网关的条件判断,优先使用扩展的配置
@author keitch
/
@SuppressWarnings("serial")
public class ExclusiveGatewayActivityBehaviorExt extends ExclusiveGatewayActivityBehavior{
protected static Logger log = LoggerFactorygetLogger(ExclusiveGatewayActivityBehaviorExtclass);
//节点的设置管理器
@Resource
BpmNodeSetManager bpmNodeSetManager;
//脚本引擎
@Resource GroovyEngine groovyEngine;
@Override
protected void leave(ActivityExecution execution) {
logdebug("enter ExclusiveGatewayActivityBehaviorExt=======================");
if (logisDebugEnabled()) {
logdebug("Leaving activity '{}'", executiongetActivity()getId());
}
String solId=(String)executiongetVariable("solId");
String nodeId=executiongetActivity()getId();
logdebug("solid is {} and nodeId is {}",solId,nodeId);
if(StringUtilsisNotEmpty(solId)&& StringUtilsisNotBlank(nodeId)){
ExclusiveGatewayConfig configs=bpmNodeSetManagergetExclusiveGatewayConfig(solId, nodeId);
for(NodeExecuteScript script:configsgetConditions()){
String destNodeId=scriptgetNodeId();
String condition=scriptgetCondition();
logdebug("dest node:{}, condition is {}",destNodeId,condition);
//执行脚本引擎
Object boolVal=groovyEngineexecuteScripts(condition, executiongetVariables());
if(boolVal instanceof Boolean){
Boolean returnVal=(Boolean)boolVal;//符合条件
if(returnVal==true){
//找到符合条件的目标节点并且进行跳转
Iterator transitionIterator = executiongetActivity()getOutgoingTransitions()iterator();
while (transitionIteratorhasNext()) {
PvmTransition seqFlow = transitionIteratornext();
if(destNodeIdequals(seqFlowgetDestination()getId())){
executiontake(seqFlow);
return;
}
}
}
}else{
throw new RuntimeException("表达式:\n "+condition+"\n返回值不为布尔值(true or false)");
}
}
}
//执行父类的写法,以使其还是可以支持旧式的在跳出线上写条件的做法
superleave(execution);
}
}
我们通过继续改写了这个分支节点的跳出机制,并且通过脚本引擎来执行其条件分支的判断处理,但流程引擎并不了解我们扩展的类,这时我们需要配置Activiti流程引擎的行为动作工厂类,如下所示:
package comredxunbpmactivitiext;
import orgactivitibpmnmodelExclusiveGateway;
import orgactivitiengineimplbpmnbehaviorExclusiveGatewayActivityBehavior;
import orgactivitiengineimplbpmnparserfactoryDefaultActivityBehaviorFactory;
/
扩展缺省的流程节点默认工厂类,实现对Activiti节点的执行的默认行为的更改
@author keitch
/
public class ActivityBehaviorFactoryExt extends DefaultActivityBehaviorFactory {
private ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt;
/
通过Spring容器注入新的分支条件行为执行类
@param exclusiveGatewayActivityBehaviorExt
/
public void setExclusiveGatewayActivityBehaviorExt(ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt) {
thisexclusiveGatewayActivityBehaviorExt = exclusiveGatewayActivityBehaviorExt;
}
//重写父类中的分支条件行为执行类
@Override
public ExclusiveGatewayActivityBehavior createExclusiveGatewayActivityBehavior(ExclusiveGateway exclusiveGateway) {
return exclusiveGatewayActivityBehaviorExt;
}
,
private static String Encode() {
JSONObject obj = new JSONObject();
ArrayList<String> array1 = new ArrayList<String>();
array1add("Class A");
array1add("Class B");
objput(CLASS_DIAGRAM_SAME, array1);
ArrayList<String> array2 = new ArrayList<String>();
array2add("Class C");
array2add("Class D");
objput(CLASS_DIAGRAM_1, array2);
ArrayList<String> array3 = new ArrayList<String>();
array3add("Class E");
array3add("Class F");
objput(CLASS_DIAGRAM_2, array3);
return objtoJSONString();
}
//=================================
CLASS_DIAGRAM_SAME等是final字符串,我就不贴了,简单的生成,一看就懂
下面两段是简单的读取,你可以举一反三,很容易明白
//=================================
Systemoutprintln(objget(CLASS_DIAGRAM_SAME));
Systemoutprintln(objget(CLASS_DIAGRAM_1));
Systemoutprintln(objget(CLASS_DIAGRAM_2));
Systemoutprintln("Same classes:");
ArrayList<String> array1 = (ArrayList<String>)objget(CLASS_DIAGRAM_SAME);
for (String same : array1) {
Systemoutprintln(same);
}
以上就是关于如何实现Activiti的分支条件的自定义配置全部的内容,包括:如何实现Activiti的分支条件的自定义配置、java web开发缓存方案,ehcache和redis哪个更好、spring mvc里,jsp中怎么获取bean等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)