activiti源碼剖析之BpmnModel模型校驗器
前言
BpmnModel校驗器可以用來校驗BpmnModel是否構(gòu)造成功昌简,可以對BpmnModel每一個元素進行合法校驗,除了BpmnModel構(gòu)造正確性校驗之外腻扇,我們還可以根據(jù)業(yè)務(wù)場景設(shè)計自定義模型校驗器细诸。比如業(yè)務(wù)需要流程中如果包含用戶任務(wù),那么用戶任務(wù)必須指定處理人等等,這種需求我們完全可以通過自定義模型校驗器進行實現(xiàn)。
一魂奥、BpmnModel模型校驗器初體驗
//創(chuàng)建模型校驗器工廠
ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
//創(chuàng)建默認模型校驗器
ProcessValidator processValidator = processValidatorFactory.createDefaultProcessValidator();
//進行模型校驗
List<ValidationError> validate = processValidator.validate(bpmnModel);
//如果校驗錯誤集合長度大于1,則說明校驗出錯易猫,遍歷打印出錯信息
if(validate.size()>=1){
for (ValidationError validationError : validate) {
System.out.println(validationError.getProblem());
System.out.println(validationError.isWarning());
}
}
二、 通過源碼分析模型校驗器
通過初體驗代碼我們大致了解到具壮,模型校驗器的步驟:
1.獲取模型校驗器工廠ProcessValidatorFactory
2.通過模型校驗器工廠創(chuàng)建模型校驗器ProcessValidator
3.調(diào)用ProcessValidator模型校驗器validate方法准颓,返回校驗結(jié)果集
- 查看processValidatorFactory.createDefaultProcessValidator()源碼
public ProcessValidator createDefaultProcessValidator() {
ProcessValidatorImpl processValidator = new ProcessValidatorImpl();
processValidator.addValidatorSet((new ValidatorSetFactory()).createActivitiExecutableProcessValidatorSet());
return processValidator;
}
- ValidatorSetFactory()).createActivitiExecutableProcessValidatorSet()實現(xiàn)
public ValidatorSet createActivitiExecutableProcessValidatorSet() {
ValidatorSet validatorSet = new ValidatorSet("activiti-executable-process");
validatorSet.addValidator(new AssociationValidator());
...
validatorSet.addValidator(new FlowElementValidator());
validatorSet.addValidator(new StartEventValidator());
validatorSet.addValidator(new SequenceflowValidator());
validatorSet.addValidator(new UserTaskValidator());
.....
validatorSet.addValidator(new DiagramInterchangeInfoValidator());
return validatorSet;
}
首先創(chuàng)建一個ProcessValidatorImpl對象,該對象持有元素為ValidatorSet的一個集合棺妓,顧名思義攘已,這個集合中包含著所有的校驗器,ProcessValidatorImpl進行模型校驗時怜跑,遍歷這個集合样勃,再針對每一個validatorSet中持有的所有Validator實現(xiàn)遍歷對BpmnModel模型進行校驗,并且將校驗錯誤添加到 List<ValidationError>集合中性芬,遍歷結(jié)束返回ValidationError結(jié)果集峡眶。
所以如果想實現(xiàn)自定義校驗器,只需要實現(xiàn)我們自己的ValidatorSet 然后添加到ProcessValidatorImpl對象中的validatorSets集合中植锉。那么如何實現(xiàn)自定義的ValidatorSet呢辫樱?我們先來看看ValidatorSet都有哪些東西
從ValidatorSet的構(gòu)成來看,校驗器的重點應(yīng)該是Validator俊庇,也就是說所有的模型校驗器都應(yīng)該實現(xiàn)Validator接口狮暑,這里我們查看Validator類結(jié)構(gòu)鸡挠,可以看出來activiti通過Validator有很多實現(xiàn),分別校驗bpmn流程文檔中不同的元素節(jié)點搬男。
三拣展、自定義Bpmn模型校驗器實戰(zhàn)
場景:在部署流程之前需要校驗流程中的所有用戶任務(wù)是否指定辦理人
- 第一步、定義校驗器類缔逛,繼承ProcessLevelValidator實現(xiàn)executeValidation方法
public class UserTaskValidator extends ProcessLevelValidator {
@Override
protected void executeValidation(BpmnModel bpmnModel, Process process, List<ValidationError> errors) {
//獲取模型中所有的用戶任務(wù)節(jié)點
List<UserTask> userTaskList = process.findFlowElementsOfType(UserTask.class);
for (UserTask userTask : userTaskList) {
//獲取用戶任務(wù)指定人
String assignee = userTask.getAssignee();
if(assignee == null || assignee == ""){
//向List<ValidationError>添加校驗錯誤結(jié)果
ValidationError validationError = new ValidationError();
validationError.setProblem(userTask.getId()+"--->沒有指定辦理人");
validationError.setWarning(false);
errors.add(validationError);
}
}
}
}
- 第二步备埃、創(chuàng)建ValidatorSet封裝自定義校驗器
ValidatorSet validatorSet = new ValidatorSet("Validate UserTask assigne");
validatorSet.addValidator(new UserTaskValidator());
- 第三步、獲取ProcessValidator的List<ValidatorSet>译株,將自定義校驗器添加進去瓜喇,對模型進行校驗
//創(chuàng)建模型校驗器工廠
ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
//創(chuàng)建默認模型校驗器
ProcessValidator processValidator = processValidatorFactory.createDefaultProcessValidator();
//添加自定義模型校驗器
List<ValidatorSet> validatorSets = processValidator.getValidatorSets();
validatorSets.add(validatorSet);
//進行模型校驗
List<ValidationError> validate = processValidator.validate(bpmnModel);
//如果校驗錯誤集合長度大于1,則說明校驗出錯歉糜,遍歷打印出錯信息
if(validate.size()>=1){
for (ValidationError validationError : validate) {
System.out.println(validationError.getProblem());
System.out.println(validationError.isWarning());
}
}
-
查看校驗結(jié)果
校驗結(jié)果.png
四乘寒、擴展源碼,將自定義模型檢驗器融合進activiti
此操作相當于將我們自定義的校驗器設(shè)置為全局檢驗匪补,這樣以后在部署流程文檔時伞辛,都會經(jīng)過我們自定義的模型校驗器,如果校驗出錯誤夯缺,則部署失敗蚤氏。那么應(yīng)該如何擴展呢
- 查看ProcessEngineConfigurationImpl.class中初始化流程校驗器實現(xiàn)
public void initProcessValidator() {
if (this.processValidator == null) {
this.processValidator = (new ProcessValidatorFactory()).createDefaultProcessValidator();
}
}
可以看到,這里先校驗processValidator開關(guān)屬性(可配置)是否為空踊兜,如果為空(用戶未設(shè)置該開關(guān)屬性)則使用默認的流程校驗器竿滨。所以我們這里通過配置processValidator開關(guān)屬性來進行擴展,當然捏境,你也可以直接擴展ProcessEngineConfigurationImpl
-
第一步于游、自定義模型檢驗器
這里不再重復(fù) - 第二步、擴展ProcessValidatorFactory,將自定義校驗器添加進去
public class ProcessValidatorFactoryExt extends ProcessValidatorFactory {
@Override
public ProcessValidator createDefaultProcessValidator() {
ProcessValidator defaultProcessValidator = super.createDefaultProcessValidator();
//將自定義校驗器添加進去
ValidatorSet validatorSet = new ValidatorSet("Validate UserTask assigne");
validatorSet.addValidator(new UserTaskValidator());
defaultProcessValidator.getValidatorSets().add(validatorSet);
return defaultProcessValidator;
}
}
- 第三步垫言、修改activit.cfg.xml贰剥,配置StandaloneProcessEngineConfiguration的開關(guān)屬性processValidator(這里修改activiti_context.xml也是類似的,也就是集成Spring)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="1234" />
<property name="databaseSchemaUpdate" value="true" />
<!--配置流程校驗器-->
<property name="processValidator">
<bean factory-bean="processValidatorFactoryExt" factory-method="createDefaultProcessValidator"/>
</property>
</bean>
<bean id="processValidatorFactoryExt" class="cn.cf.activiti.shareniu.ProcessValidatorFactoryExt"/>
</beans>
-
部署一個流程文檔,流程文檔中的用戶任務(wù)不分配處理人的結(jié)果
部署結(jié)果.png