提交 8da00dd3 编写于 作者: zhouweidong's avatar zhouweidong

适配动态系统

上级 aaf4fcd1
......@@ -9,6 +9,37 @@ TARGET=PSDELOGIC
<tns:import name="java.util.Map" />
<tns:import name="org.springframework.util.StringUtils"/>
<tns:import name="${pub.getPKGCodeName()}.util.helper.RuleUtils"/>
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
<#comment>插入逻辑参数</#comment>
<#if item.getPSDELogicParams?? && item.getPSDELogicParams()??>
<#assign logicName=(de.codeName+item.codeName)?lower_case>
<#list item.getPSDELogicParams() as logicParam>
<#assign paramObj=(logicName+logicParam.codeName)?lower_case>
<#if logicParam.isDefault()==true><#comment>默认变量</#comment>
<tns:metaData express="" name="${paramObj}" type="entity"/>
<#elseif logicParam.getParamPSDataEntity?? && logicParam.getParamPSDataEntity()??>
<#assign ParamPSDataEntity=logicParam.getParamPSDataEntity()>
<tns:metaData express="new ${pub.getPKGCodeName()}.core.${ParamPSDataEntity.getPSSystemModule().codeName?lower_case}.domain.${ParamPSDataEntity.codeName}()" name="${(logicName+logicParam.codeName)?lower_case}" type="ref"/>
<#else>
<tns:metaData express="new HashMap()" name="${(logicName+logicParam.codeName)?lower_case}" type="ref"/>
</#if>
</#list>
</#if>
<#comment>插入处理逻辑中所用到的service对象</#comment>
<#if item.getPSDELogicNodes?? && item.getPSDELogicNodes()??>
<#list item.getPSDELogicNodes() as deLogicNode>
<#if deLogicNode.getDstPSDataEntity?? && deLogicNode.getDstPSDataEntity()??>
<#assign nodePSDataEntity=deLogicNode.getDstPSDataEntity()>
<#if !P.exists(item.codeName,"kieSessionGlobalServiceBpmn",deLogicNode.getDstPSDataEntity().getCodeName()?lower_case)>
<tns:metaData express="T(${pub.getPKGCodeName()}.util.security.SpringContextHolder).getBean(T(${pub.getPKGCodeName()}.core.${nodePSDataEntity.getPSSystemModule().codeName?lower_case}.service.I${nodePSDataEntity.codeName}Service))" name="${deLogicNode.getDstPSDataEntity().getCodeName()?lower_case}service" type="service"/>
</#if>
</#if>
</#list>
</#if>
<#comment>插入当前实体的defaultService对象,供自定义查询使用</#comment>
<tns:metaData express="T(${pub.getPKGCodeName()}.util.security.SpringContextHolder).getBean(T(${pub.getPKGCodeName()}.core.${de.getPSSystemModule().codeName?lower_case}.service.I${de.codeName}Service))" name="iBzSys${de.codeName?lower_case?cap_first}DefaultService" type="service"/>
<tns:metaData express="T(${pub.getPKGCodeName()}.util.security.AuthenticationUser).getAuthenticationUser()" name="curuser" type="session"/>
</#if>
<#assign logicName=(de.codeName+item.codeName)?lower_case>
<#comment>插入逻辑参数</#comment>
<#if item.getPSDELogicParams?? && item.getPSDELogicParams()??>
......
<#ibiztemplate>
TARGET=PSDEACTION
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
<#assign hasAfterLogic = false>
<#if item.getAfterPSDEActionLogics?? && item.getAfterPSDEActionLogics()??>
<#list item.getAfterPSDEActionLogics() as afterlogic>
<#assign hasAfterLogic = true>
<#break>
</#list>
</#if>
<#if hasAfterLogic>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:g="http://www.jboss.org/drools/flow/gpd" xmlns:tns="http://www.jboss.org/drools" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.mvel.org/2.0" id="Definition" name="" targetNamespace="http://www.jboss.org/drools" typeLanguage="http://www.java.com/javaTypes">
<process id="${pub.getPKGCodeName()}.core.extensions.service.logic.after" isClosed="false" isExecutable="true" name="ScoreRule" processType="Private" tns:packageName="${pub.getPKGCodeName()}.core.extensions.service.logic.after">
<extensionElements>
<tns:import name="java.util.Map"/>
<tns:import name="org.springframework.util.StringUtils"/>
<tns:import name="${pub.getPKGCodeName()}.util.helper.RuleUtils"/>
</extensionElements>
<#if item.getAfterPSDEActionLogics?? && item.getAfterPSDEActionLogics()??>
<startEvent id="begin" isInterrupting="true"/>
<endEvent id="prepareparam1_end" name="end"/>
<#assign source="begin">
<#list item.getAfterPSDEActionLogics() as afterlogic>
<#comment>实体行为附加逻辑</#comment>
<#if afterlogic.getPSDELogic()?? && afterlogic.getPSDELogic().isEnableBackend()>
<#assign target =afterlogic.getId()>
<#assign delogic = afterlogic.getPSDELogic()>
<callActivity activiti:exclusive="true" calledElement="${pub.getPKGCodeName()}.core.${de.getPSSystemModule().codeName?lower_case}.service.logic.${de.codeName?lower_case}${delogic.getCodeName()?lower_case}" id="${target}" name="${delogic.codeName}"/>
<#else>
</#if>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="${target}"/>
<#assign source = target>
<#if !afterlogic_has_next>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="prepareparam1_end"/>
</#if>
</#list>
</#if>
</process>
</definitions>
</#if>
</#if>
\ No newline at end of file
<#ibiztemplate>
TARGET=PSDEACTION
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
<#assign hasBeforeLogic =false>
<#if item.getBeforePSDEActionLogics?? && item.getBeforePSDEActionLogics()??>
<#list item.getBeforePSDEActionLogics() as beforelogic>
<#assign hasBeforeLogic=true>
<#break>
</#list>
</#if>
<#if hasBeforeLogic>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:g="http://www.jboss.org/drools/flow/gpd" xmlns:tns="http://www.jboss.org/drools" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.mvel.org/2.0" id="Definition" name="" targetNamespace="http://www.jboss.org/drools" typeLanguage="http://www.java.com/javaTypes">
<process id="${pub.getPKGCodeName()}.core.extensions.service.logic.before" isClosed="false" isExecutable="true" name="ScoreRule" processType="Private" tns:packageName="${pub.getPKGCodeName()}.core.extensions.service.logic.before">
<extensionElements>
<tns:import name="java.util.Map"/>
<tns:import name="org.springframework.util.StringUtils"/>
<tns:import name="${pub.getPKGCodeName()}.util.helper.RuleUtils"/>
</extensionElements>
<#if item.getBeforePSDEActionLogics?? && item.getBeforePSDEActionLogics()??>
<startEvent id="begin" isInterrupting="true"/>
<endEvent id="prepareparam1_end" name="end"/>
<#assign source="begin">
<#list item.getBeforePSDEActionLogics() as beforelogic>
<#comment>实体行为附加逻辑</#comment>
<#if beforelogic.getPSDELogic()??>
<#assign delogic = beforelogic.getPSDELogic()>
<#assign target =beforelogic.getId()>
<callActivity activiti:exclusive="true" calledElement="${pub.getPKGCodeName()}.core.${de.getPSSystemModule().codeName?lower_case}.service.logic.${de.codeName?lower_case}${delogic.getCodeName()?lower_case}" id="${target}" name="${delogic.codeName}"/>
<#else>
</#if>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="${target}"/>
<#assign source = target>
<#if !beforelogic_has_next>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="prepareparam1_end"/>
</#if>
</#list>
</#if>
</process>
</definitions>
</#if>
</#if>
\ No newline at end of file
<#ibiztemplate>
TARGET=PSDEACTION
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
<#if item.getActionType()=='DELOGIC' && item.getPSDELogic()??>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:g="http://www.jboss.org/drools/flow/gpd" xmlns:tns="http://www.jboss.org/drools" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.mvel.org/2.0" id="Definition" name="" targetNamespace="http://www.jboss.org/drools" typeLanguage="http://www.java.com/javaTypes">
<process id="${pub.getPKGCodeName()}.core.extensions.service.logic.execute" isClosed="false" isExecutable="true" name="ScoreRule" processType="Private" tns:packageName="${pub.getPKGCodeName()}.core.extensions.service.logic.execute">
<extensionElements>
<tns:import name="java.util.Map"/>
<tns:import name="org.springframework.util.StringUtils"/>
<tns:import name="${pub.getPKGCodeName()}.util.helper.RuleUtils"/>
</extensionElements>
<#comment>实体行为附加逻辑</#comment>
<#assign delogic = item.getPSDELogic()>
<#assign source="begin">
<#assign action=item.getPSDELogic()>
<startEvent id="begin" isInterrupting="true"/>
<endEvent id="prepareparam1_end" name="end"/>
<#assign target = action.getCodeName()>
<callActivity activiti:exclusive="true" calledElement="${pub.getPKGCodeName()}.core.${de.getPSSystemModule().codeName?lower_case}.service.logic.${de.codeName?lower_case}${delogic.getCodeName()?lower_case}" id="${target}" name="${delogic.codeName}"/>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="${target}"/>
<#assign source = target>
<sequenceFlow id="${source}_${target}" sourceRef="${source}" targetRef="prepareparam1_end"/>
</process>
</definitions>
</#if>
</#if>
\ No newline at end of file
......@@ -123,7 +123,9 @@ TARGET=PSSYSTEM
<#if hasMQEntity>
<rocketmq.version>4.7.0</rocketmq.version>
</#if>
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
<flowable-modeler.version>6.4.2</flowable-modeler.version>
</#if>
</properties>
<#-- dependencies,just for statement, manage the version of jars -->
......@@ -327,7 +329,7 @@ TARGET=PSSYSTEM
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version> ${r'${spring-cloud-alibaba.version}'}</version>
<version>${r'${spring-cloud-alibaba.version}'}</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
......@@ -337,6 +339,18 @@ TARGET=PSSYSTEM
</dependency>
</#if>
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${r'${flowable-modeler.version}'}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-conf</artifactId>
<version>${r'${flowable-modeler.version}'}</version>
</dependency>
</#if>
</dependencies>
</dependencyManagement>
......
......@@ -93,5 +93,33 @@ TARGET=PSSYSTEM
<artifactId>feign-httpclient</artifactId>
</dependency>
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
<!-- drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-conf</artifactId>
</dependency>
</#if>
</dependencies>
</project>
<#ibiztemplate>
TARGET=PSSYSTEM
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
package ${pub.getPKGCodeName()}.util.aspect;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import ${pub.getPKGCodeName()}.util.domain.DELogic;
import ${pub.getPKGCodeName()}.util.domain.EntityBase;
import ${pub.getPKGCodeName()}.util.errors.BadRequestAlertException;
import org.apache.commons.io.IOUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 实体处理逻辑切面(前后附加逻辑、实体行为调用处理逻辑)
*/
@Aspect
@Component
@Slf4j
public class DELogicAspect {
@Value("${r'${ibiz.filePath:D:/app/file/}'}")
private String fileRoot;
private static BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
private final ExpressionParser parser = new SpelExpressionParser();
private ConcurrentMap<String, DELogic> deLogicMap = new ConcurrentHashMap<>();
private final String DEFAULT_MODULE_PACKAGE = "[\\w+\\.]\\.core.(\\w+)\\.domain";
@Value("${r'${ibiz.dynamicMode:false}'}")
private boolean dynamicMode;
@Value("${r'${ibiz.dynamic.path:/app/file/dynamicmodel/}'}")
private String dynamicPath;
@Value("${r'$'}{ibiz.systemid:${sys.getCodeName()}}")
private String systemId;
/**
* 执行实体行为附加逻辑、实体行为调用处理逻辑
*
* @param point
* @return
* @throws Throwable
*/
@Around("execution(* ${pub.getPKGCodeName()}.core.*.service.*.*(..))")
public Object executeLogic(ProceedingJoinPoint point) throws Throwable {
Object args[] = point.getArgs();
if (ObjectUtils.isEmpty(args) || args.length == 0) {
return point.proceed();
}
Object arg = args[0];
if (arg instanceof EntityBase) {
String action = point.getSignature().getName();
EntityBase entity = (EntityBase) arg;
executeBeforeLogic(entity, action);
Object result = point.proceed();
executeLogic(entity, action);
executeAfterLogic(entity, action);
return result;
}
return point.proceed();
}
/**
* 前附加逻辑
*
* @param entity
* @param action
*/
private void executeBeforeLogic(EntityBase entity, String action) {
File bpmnFile;
if (dynamicMode) {
bpmnFile = getRemoteModel(getDEModule(entity), entity.getClass().getSimpleName(), action, "before");
if (bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
return;
}
}
bpmnFile = getLocalModel(entity.getClass().getSimpleName(), action, "before");
if (bpmnFile != null && bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
}
}
/**
* 后附加逻辑
*
* @param entity
* @param action
*/
private void executeAfterLogic(EntityBase entity, String action) {
File bpmnFile;
if (dynamicMode) {
bpmnFile = getRemoteModel(getDEModule(entity), entity.getClass().getSimpleName(), action, "after");
if (bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
return;
}
}
bpmnFile = getLocalModel(entity.getClass().getSimpleName(), action, "after");
if (bpmnFile != null && bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
}
}
/**
* 实体行为调用处理逻辑
*
* @param entity
* @param action
*/
private void executeLogic(EntityBase entity, String action) {
File bpmnFile;
if (dynamicMode) {
bpmnFile = getRemoteModel(getDEModule(entity), entity.getClass().getSimpleName(), action, "exec");
if (bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
return;
}
}
bpmnFile = getLocalModel(entity.getClass().getSimpleName(), action, "exec");
if (bpmnFile != null && bpmnFile.exists()) {
executeLogic(bpmnFile, entity);
}
}
/**
* 编译并执行规则(bpmndrl
*
* @param bpmnFile
* @param entity
*/
private void executeLogic(File bpmnFile, Object entity) {
log.debug("开始执行实体处理逻辑[{}]", bpmnFile.getName());
String bpmnId = DigestUtils.md5DigestAsHex(bpmnFile.getName().getBytes());
DELogic logic = getDELogic(bpmnFile, entity);
if (logic == null) {
return;
}
if (deLogicMap.containsKey(bpmnId) && logic.getMd5().equals(deLogicMap.get(bpmnId).getMd5())) {
logic = deLogicMap.get(bpmnId);
} else {
reloadLogic(logic);
deLogicMap.put(bpmnId, logic);
}
KieContainer container = logic.getContainer();
KieSession kieSession = container.getKieBase().newKieSession();
Process mainProcess = logic.getProcess();
//主流程参数
fillGlobalParam(kieSession, mainProcess, entity);
//子流程参数
if (!ObjectUtils.isEmpty(logic.getRefLogic())) {
for (DELogic subLogic : logic.getRefLogic()) {
fillGlobalParam(kieSession, subLogic.getProcess(), entity);
}
}
kieSession.startProcess(mainProcess.getId());
log.debug("实体处理逻辑[{}]执行结束", bpmnFile.getName());
}
/**
* 编译规则
*
* @param logic
*/
private void reloadLogic(DELogic logic) {
KieServices kieServices = KieServices.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
for (File bpmn : logic.getRefRuleFiles()) {
kieFileSystem.write(ResourceFactory.newFileResource(bpmn));
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll();
Results results = kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
throw new BadRequestAlertException(String.format("编译实体处理逻辑 [%s] 发生异常, %s", logic.getName(), results.getMessages()), "LogicAspect", "reloadLogic");
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
logic.setContainer(kieContainer);
}
/**
* 填充逻辑参数
*
* @param kieSession
* @param process
* @param entity
*/
private void fillGlobalParam(KieSession kieSession, Process process, Object entity) {
Map<String, List<ExtensionElement>> params = process.getExtensionElements();
for (Map.Entry<String, List<ExtensionElement>> param : params.entrySet()) {
if ("metaData".equalsIgnoreCase(param.getKey())) {
List<ExtensionElement> globalParams = param.getValue();
for (ExtensionElement globalParam : globalParams) {
Object value = null;
Map<String, List<ExtensionAttribute>> globalParamAttr = globalParam.getAttributes();
ExtensionAttribute name = globalParamAttr.get("name").get(0);
ExtensionAttribute type = globalParamAttr.get("type").get(0);
ExtensionAttribute express = globalParamAttr.get("express").get(0);
String express_value = express.getValue();
EvaluationContext oldContext = new StandardEvaluationContext();
if ("entity".equalsIgnoreCase(type.getValue())) {
value = entity;
}
if (!ObjectUtils.isEmpty(type.getValue()) && ObjectUtils.isEmpty(value)) {
Expression oldExp = parser.parseExpression(express_value);
value = oldExp.getValue(oldContext);
}
kieSession.setGlobal(name.getValue(), value);
}
}
}
}
/**
* 获取逻辑配置
*
* @param bpmnFile
* @param entity
* @return
*/
@SneakyThrows
private DELogic getDELogic(File bpmnFile, Object entity) {
DELogic logic = null;
XMLStreamReader reader = null;
InputStream bpmn = null;
try {
if (bpmnFile.exists()) {
XMLInputFactory factory = XMLInputFactory.newInstance();
bpmn = new FileInputStream(bpmnFile);
reader = factory.createXMLStreamReader(bpmn);
BpmnModel model = bpmnXMLConverter.convertToBpmnModel(reader);
Process mainProcess = model.getMainProcess();
if (mainProcess == null) {
return null;
}
List<DELogic> refLogics = new ArrayList<>();
List<File> refFiles = new ArrayList<>();
//自己 bpmn drl
refFiles.add(bpmnFile);
File drlFile = getDrl(bpmnFile);
if (drlFile.exists()) {
refFiles.add(drlFile);
}
// bpmn drl
if (!ObjectUtils.isEmpty(model.getMainProcess()) && !ObjectUtils.isEmpty(model.getMainProcess().getFlowElementMap())) {
model.getMainProcess().getFlowElementMap().values().forEach(item -> {
if (item instanceof CallActivity) {
CallActivity subBpmn = (CallActivity) item;
String bpmnFileName = subBpmn.getName();
File subBpmnFile = getSubBpmn(getDEModule(entity), entity.getClass().getSimpleName(), bpmnFileName);
DELogic refLogic = getDELogic(subBpmnFile, entity);
if (refLogic != null) {
refLogics.add(refLogic);
if (!ObjectUtils.isEmpty(refLogic.getRefRuleFiles())) {
refFiles.addAll(refLogic.getRefRuleFiles());
}
}
}
});
}
logic = new DELogic();
logic.setId(mainProcess.getId());
logic.setName(mainProcess.getName());
logic.setProcess(mainProcess);
logic.setRefLogic(refLogics);
logic.setRefRuleFiles(refFiles);
logic.setMd5(getMd5(refFiles));
}
} catch (Exception e) {
} finally {
try {
if (reader != null) {
reader.close();
}
if (bpmn != null) {
bpmn.close();
}
} catch (Exception e) {
}
}
return logic;
}
/**
* 获取bpmn md5
*
* @param subFiles
* @return
*/
private String getMd5(List<File> subFiles) {
try {
StringBuffer buffer = new StringBuffer();
for (File file : subFiles) {
InputStream bpmnFile = null;
try {
bpmnFile = new FileInputStream(file);
if (!ObjectUtils.isEmpty(bpmnFile)) {
String strBpmn = IOUtils.toString(bpmnFile, "UTF-8");
buffer.append(strBpmn);
}
} catch (Exception e) {
} finally {
if (bpmnFile != null) {
bpmnFile.close();
}
}
}
if (!StringUtils.isEmpty(buffer.toString())) {
return DigestUtils.md5DigestAsHex(buffer.toString().getBytes());
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
/**
* 远程逻辑
*
* @param entity
* @param action
* @param actionLogic
* @return
*/
private File getLocalModel(String entity, String action, String actionLogic) {
String logicName = String.format("PSDEACTION.json.%s.bpmn", actionLogic);
String filePath = File.separator + "rules" + File.separator + entity.toLowerCase() + File.separator + action + File.separator + logicName;
URL url = this.getClass().getResource(filePath.replace("\\", "/"));
return ObjectUtils.isEmpty(url) ? null : new File(url.getPath());
}
/**
* 本地逻辑
*
* @param module
* @param entity
* @param action
* @param actionLogic
* @return
*/
private File getRemoteModel(String module, String entity, String action, String actionLogic) {
String logicName = String.format("PSDEACTION.json.%s.bpmn", actionLogic);
return new File(dynamicPath + File.separator + systemId + File.separator + "PSMODULES" + File.separator + module + File.separator + "PSDATAENTITIES" + File.separator + entity + File.separator + "PSDEACTIONS" + File.separator + action + File.separator + logicName);
}
/**
* 处理逻辑 bpmn
*
* @param module
* @param entity
* @param logicName
* @return
*/
private File getSubBpmn(String module, String entity, String logicName) {
if (dynamicMode) {
return new File(dynamicPath + File.separator + systemId + File.separator + "PSMODULES" + File.separator + module + File.separator + "PSDATAENTITIES" + File.separator + entity + File.separator + "PSDELOGICS" + File.separator + logicName + File.separator + "PSDELOGIC.json.bpmn");
} else {
String filePath = String.format("/rules/%s%sRuleFlow.bpmn", entity, logicName);
return ObjectUtils.isEmpty(this.getClass().getResource(filePath)) ? null : new File(this.getClass().getResource(filePath).getPath());
}
}
/**
* 处理逻辑 drl
*
* @param bpmn
* @return
*/
private File getDrl(File bpmn) {
if (bpmn.getPath().endsWith("RuleFlow.bpmn")) {
return new File(bpmn.getPath().replace("RuleFlow.bpmn", "Rule.drl"));
} else {
return new File(bpmn.getPath().replace(".bpmn", ".drl"));
}
}
/**
* 获取实体模块
*
* @param entity
* @return
*/
private String getDEModule(Object entity) {
String strModule = null;
String packageName = entity.getClass().getPackage().getName();
Pattern p = Pattern.compile(DEFAULT_MODULE_PACKAGE);
Matcher m = p.matcher(packageName);
while (m.find()) {
strModule = m.group(1);
}
if (StringUtils.isEmpty(strModule)) {
throw new BadRequestAlertException(String.format("无法获取实体[%s]所属模块信息", entity.getClass().getSimpleName()), "LogicAspect", "getDEModule");
}
return strModule;
}
}
</#if>
\ No newline at end of file
......@@ -127,6 +127,9 @@ public class RedisCacheConfig {
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DYNAMICMODEL_TOPIC.getChannelTopic());
</#if>
return container;
}
}
\ No newline at end of file
......@@ -15,6 +15,10 @@ import org.springframework.util.ObjectUtils;
import java.util.Map;
import ${pub.getPKGCodeName()}.util.cache.cache.LayeringCache;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
import ${pub.getPKGCodeName()}.util.security.SpringContextHolder;
import ${pub.getPKGCodeName()}.util.service.DynamicModelService;
</#if>
/**
* redis消息的订阅者
......@@ -45,6 +49,13 @@ public class RedisMessageListener extends MessageListenerAdapter {
log.debug("redis消息订阅者接收到频道【{}】发布的消息。消息内容:{}", channelTopic.getChannelTopicStr(), result.toString());
String cacheName = (String) map.get("cacheName");
Cache cache = cacheManager.getCache(cacheName);// 根据缓存名称获取多级缓存
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
if (channelTopic.equals(RedisChannelTopic.REDIS_CACHE_DYNAMICMODEL_TOPIC)) {
DynamicModelService dynamicModelService = SpringContextHolder.getBean(DynamicModelService.class);
dynamicModelService.syncModel();
return;
}
</#if>
if (cache != null && cache instanceof LayeringCache) { // 判断缓存是否是多级缓存
switch (channelTopic) {
case REDIS_CACHE_DELETE_TOPIC: // 获取一级缓存,并删除一级缓存数据
......
<#ibiztemplate>
TARGET=PSSYSTEM
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
package ${pub.getPKGCodeName()}.util.domain;
import lombok.Data;
import org.flowable.bpmn.model.Process;
import org.kie.api.runtime.KieContainer;
import java.io.File;
import java.io.Serializable;
import java.util.List;
@Data
public class DELogic implements Serializable {
String id;
String name;
Process process;
KieContainer container;
List<DELogic> refLogic;
List<File> refRuleFiles;
String md5;
}
</#if>
\ No newline at end of file
......@@ -9,6 +9,9 @@ import org.springframework.data.redis.listener.ChannelTopic;
*/
public enum RedisChannelTopic {
REDIS_CACHE_DELETE_TOPIC("redis:cache:delete:topic1", "删除redis缓存消息频道"),
<#if pub.isEnableDynaModel()?? && pub.isEnableDynaModel()== true>
REDIS_CACHE_DYNAMICMODEL_TOPIC("redis:cache:dynamicmodel:topic3", "动态模型频道"),
</#if>
REDIS_CACHE_CLEAR_TOPIC("redis:cache:clear:topic2", "清空redis缓存消息频道");
String channelTopic;
......
<#ibiztemplate>
TARGET=PSSYSTEM
</#ibiztemplate>
<#if sys.getCodeName()=='Sample'>
package ${pub.getPKGCodeName()}.util.service;
import lombok.extern.slf4j.Slf4j;
import ${pub.getPKGCodeName()}.util.client.IBZLiteFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.io.*;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class DynamicModelService {
@Value("${r'$'}{ibiz.systemid:${sys.getCodeName()}}")
private String systemId;
@Value("${r'${ibiz.dynamic.path:/app/file/dynamicmodel/}'}")
private String dynamicPath;
@Autowired
IBZLiteFeignClient liteClient;
/**
* 同步动态模型
* @return
*/
public boolean syncModel() {
log.debug("开始同步动态模型");
long start = System.currentTimeMillis();
List<Map<String, Object>> dynamicModels = liteClient.getDynamicModel(systemId);
if (!ObjectUtils.isEmpty(dynamicModels)) {
File dynamicFolder = new File(dynamicPath + File.separator + systemId);
if (dynamicFolder.exists()) {
deleteDir(dynamicFolder.getPath());
}
for (Map<String, Object> dynamicModel : dynamicModels) {
InputStream inputStream = null;
BufferedInputStream bufferedInputStream = null;
FileOutputStream outputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
String strFileName = String.valueOf(dynamicModel.get("filename"));
String strFilePath = String.valueOf(dynamicModel.get("filepath"));
Object strFileContent = dynamicModel.get("filecontent");
String fullPath = dynamicPath + strFilePath;
File parent = new File(fullPath.replace(strFileName, ""));
if (!parent.exists()) {
parent.mkdirs();
}
File file = new File(fullPath);
file.createNewFile();
// 文件输入流并进行缓冲
inputStream = new ByteArrayInputStream(String.valueOf(strFileContent).getBytes());
bufferedInputStream = new BufferedInputStream(inputStream);
// 文件输出流并进行缓冲
outputStream = new FileOutputStream(file);
bufferedOutputStream = new BufferedOutputStream(outputStream);
// 缓冲数组,大文件 可将 1024 * 2 改大一些,但是 并不是越大就越快
byte[] bytes = new byte[1024 * 2];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
// 刷新输出缓冲流
bufferedOutputStream.flush();
log.debug(fullPath);
} catch (IOException e) {
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
}
}
}
}
long end = System.currentTimeMillis();
log.debug("动态模型同步完成,共耗时"+ (end - start) / 1000 + " 秒");
return true;
}
/**
* 删除历史动态模型
* @param dirPath
*/
public void deleteDir(String dirPath) {
File file = new File(dirPath);
if (file.isFile()) {
file.delete();
} else {
File[] files = file.listFiles();
if (files == null) {
file.delete();
} else {
for (int i = 0; i < files.length; i++) {
deleteDir(files[i].getAbsolutePath());
}
file.delete();
}
}
}
}
</#if>
\ No newline at end of file
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册