All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iqiny.silly.spring.SpringSillyConfigContent Maven / Gradle / Ivy

/*
 *  Copyright  iqiny.com
 *
 *  https://gitee.com/iqiny/silly
 *
 *  project name:silly-spring
 *  project description:top silly project pom.xml file
 */
package com.iqiny.silly.spring;

import com.iqiny.silly.common.SillyConstant;
import com.iqiny.silly.common.exception.SillyException;
import com.iqiny.silly.common.util.SillyAssert;
import com.iqiny.silly.common.util.SillyObjectUtil;
import com.iqiny.silly.common.util.SillyReflectUtil;
import com.iqiny.silly.core.base.*;
import com.iqiny.silly.core.base.core.SillyEntity;
import com.iqiny.silly.core.base.core.SillyRootData;
import com.iqiny.silly.core.common.SillyCoreUtil;
import com.iqiny.silly.core.common.SillyExecutorUtil;
import com.iqiny.silly.core.config.BaseSillyConfigContent;
import com.iqiny.silly.core.config.SillyCategoryConfig;
import com.iqiny.silly.core.config.property.SillyProcessProperty;
import com.iqiny.silly.core.config.property.SillyPropertyHandle;
import com.iqiny.silly.core.data.SillyCategoryJsonData;
import com.iqiny.silly.core.engine.SillyEngineService;
import com.iqiny.silly.core.group.SillyTaskCategoryGroup;
import com.iqiny.silly.core.resume.SillyResumeService;
import com.iqiny.silly.core.savehandle.SillyOnceSourceData;
import com.iqiny.silly.core.service.SillyReadService;
import com.iqiny.silly.core.service.SillyWriteService;
import com.iqiny.silly.core.service.crud.SillyCrudService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import static org.springframework.util.StringUtils.tokenizeToStringArray;

@SuppressWarnings("all")
public class SpringSillyConfigContent extends BaseSillyConfigContent {

    private final static Log log = LogFactory.getLog(SpringSillyConfigContent.class);

    protected static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();

    protected String processPattern;

    protected Class defaultEngineServiceClazz;

    protected Class defaultWriteServiceClazz;

    protected Class defaultReadServiceClazz;

    protected Class defaultResumeServiceClazz;

    protected Class nodeSourceDataClazz;

    protected Class processPropertyClazz;

    protected Class propertyHandleClazz;

    protected Class rootDataClazz;

    protected Class defaultTaskCategoryGroupClazz;


    private String[] categories;

    private boolean loadCategoryFlag = false;

    public SpringSillyConfigContent(SillyProperties sillyProperties, SillyContext sillyContext) {
        super(sillyProperties, sillyContext);
    }

    @Override
    protected void preInit() {
        log.info("SpringSillyConfigContent  " + this.getClass().getName() + " 初始化开始");
        SillyAssert.notNull(sillyProperties, "sillyProperties 配置属性不可为空");

        this.processPattern = sillyProperties.getProcessPattern();
        this.defaultEngineServiceClazz = sillyProperties.getDefaultEngineServiceClazz();
        this.defaultWriteServiceClazz = sillyProperties.getDefaultWriteServiceClazz();
        this.defaultReadServiceClazz = sillyProperties.getDefaultReadServiceClazz();
        this.defaultResumeServiceClazz = sillyProperties.getDefaultResumeServiceClazz();
        this.processPropertyClazz = sillyProperties.getProcessPropertyClazz();
        this.propertyHandleClazz = sillyProperties.getPropertyHandleClazz();
        this.defaultTaskCategoryGroupClazz = sillyProperties.getDefaultTaskCategoryGroupClazz();
        this.nodeSourceDataClazz = sillyProperties.getDefaultNodeSourceDataClazz();
        this.categories = sillyProperties.getCategories();
    }

    @Override
    protected void initFiled() {
        this.loadCategoryFlag = false;
        super.initFiled();
    }

    @Override
    protected synchronized void loadCategorySet() {
        if (loadCategoryFlag) {
            return;
        }

        loadCategoryFlag = true;
        if (categories != null) {
            for (String category : categories) {
                addCategorySet(category);
            }
        }
    }

    @Override
    protected void initBaseSillyFactoryList() {
        throw new SillyException("initBaseSillyFactoryList 此方法未实现");
    }

    @Override
    protected SillyCrudService registerSillyCRUDService(Class entityClazz) {
        String sillyCRDUServiceBeanName = SillyContext.getSillyCRDUServiceBeanName(entityClazz);
        Class crudServiceClazz = sillyProperties.getDefaultCrudServiceClazz();
        return sillyContext.registerBean(
                sillyCRDUServiceBeanName,
                crudServiceClazz,
                bdb -> {
                    SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                    ((BeanDefinitionBuilder) bdb).addPropertyValue("entityClazz", entityClazz);
                });
    }

    @Override
    protected void hookSillyProcessPropertyList() {
        SillyExecutorUtil.lockObjExecute(SillyCategory.DEFAULT_CATEGORY, this, config -> {
            refreshProcessResource();
            return null;
        });
    }

    /**
     * 加载/刷新傻瓜流程配置资源
     */
    public void refreshProcessResource() {
        // 加载文件形式的业务JSON数据配置(将文件配置转存到数据库)
        List resources = getCategoryResources();
        List jsonPropertys = new ArrayList<>();
        for (Resource resource : resources) {
            final SillyProcessProperty property = loadSillyProcessProperty(resource);
            if (property != null) {
                jsonPropertys.add(property);
            }
        }
        if (jsonDataClazz == null) {
            // 加载文件形式的JSON数据配置
            for (SillyProcessProperty property : jsonPropertys) {
                addSillyProcessProperty(property);
            }
        } else {
            // 加载数据库形式的JSON数据配置
            final SillyCrudService sillyJsonSerivce = sillyContext.getSillyCrudService(jsonDataClazz);
            SillyAssert.notNull(sillyJsonSerivce, "SillyCategoryJsonData 对象CRUD服务未找到,请完成配置");
            final SillyCategoryJsonData jsonData = SillyReflectUtil.newInstance(sillyJsonSerivce.getEntityClazz());
            jsonData.setStatus(SillyConstant.SillyNodeStatus.STATUS_CURRENT);
            final List categoryJsonList = sillyJsonSerivce.selectList(jsonData);
            for (SillyCategoryJsonData sillyCategoryJsonData : categoryJsonList) {
                final SillyProcessProperty sillyProcessProperty = doCreateSillyProperty(sillyCategoryJsonData.getCategory(), sillyCategoryJsonData.getJsonData());
                addSillyProcessProperty(sillyProcessProperty);
            }
        }

    }

    protected SillyProcessProperty loadSillyProcessProperty(Resource resource) {
        if (resource == null || !resource.isReadable()) {
            log.warn(resource == null ? "无数据" : resource.getFilename() + "不可读取,将跳过加载");
            return null;
        }
        try (
                InputStream inputStream = resource.getInputStream();
                StringWriter writer = new StringWriter();
        ) {
            // 生成jar后必须以流的形式读取
            IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8.name());
            String json = writer.toString();
            String fileName = resource.getFilename();
            SillyProcessProperty sillyProcessProperty = doCreateSillyProperty(fileName.substring(0, fileName.lastIndexOf(".")), json);
            final String category = sillyProcessProperty.getCategory();
            if (jsonDataClazz == null) {
                // 不进行数据存储,仅读取文件
                return sillyProcessProperty;
            } else {
                // 查询数据库中是否存在相同业务且KEY值相同的数据
                final SillyCrudService sillyJsonSerivce = sillyContext.getSillyCrudService(jsonDataClazz);
                SillyAssert.notNull(sillyJsonSerivce, "SillyCategoryJsonData 对象CRUD服务未找到,请完成配置");
                final SillyCategoryJsonData jsonData = SillyReflectUtil.newInstance(sillyJsonSerivce.getEntityClazz());
                jsonData.setCategory(category);
                final String md5key = DigestUtils.md5Hex(json);
                jsonData.setJsonKey(md5key);
                // 若存在,则跳过
                final long count = sillyJsonSerivce.selectCount(jsonData);
                if (count == 0) {
                    // 若不存在则将数据库数据状态设置为历史
                    final SillyCategoryJsonData whereJsonData = SillyReflectUtil.newInstance(sillyJsonSerivce.getEntityClazz());
                    whereJsonData.setCategory(category);
                    final SillyCategoryJsonData setJsonData = SillyReflectUtil.newInstance(sillyJsonSerivce.getEntityClazz());
                    setJsonData.setCategory(category);
                    setJsonData.setStatus(SillyConstant.SillyNodeStatus.STATUS_HISTORY);
                    sillyJsonSerivce.update(setJsonData, whereJsonData);
                    // 再将当前数据存档
                    jsonData.setJsonData(json);
                    jsonData.setStatus(SillyConstant.SillyNodeStatus.STATUS_CURRENT);
                    sillyJsonSerivce.insert(jsonData);
                    log.info("成功更新流程配置文件到数据库:" + category);
                }
            }
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
        }
        return null;
    }

    protected SillyProcessProperty doCreateSillyProperty(String category, String json) {
        // 按定义顺序生成
        Class sillyProcessPropertyClass = getProcessPropertyClazz(category);
        SillyProcessProperty processProperty = SillyObjectUtil.toObject(json, sillyProcessPropertyClass);
        SillyAssert.notEmpty(processProperty.getCategory(), category + " category不可为空");
        return processProperty;
    }

    @Override
    protected void initComplete() {
        log.info(this.getClass().getName() + " 初始化完成");
        log.info("转换器:" + sillyConvertorList.size() + "个,对象工厂:" + sillyFactoryList.size() + "个," +
                "读取服务:" + sillyReadServiceList.size() + "个,写入服务:" + sillyWriteServiceList.size() + "个," +
                "流程属性:" + sillyProcessPropertyList.size() + "个");
        log.info("成功注册" + sillyTaskGroupHandle.allSillyTaskGroup().size() + " 个任务组对象");
        log.info("成功注册" + sillyTaskGroupHandle.allCategoryGroup().size() + " 个类型任务组对象");
        log.info("已成功加载分类数量:" + allCategorySet().size() + " 种");
        log.info("已成功加载分类:" + allCategorySet() + "");
    }

    public Class getProcessPropertyClazz(String category) {
        SillyFactory sillyFactory = getSillyFactory(category);
        if (sillyFactory != null) {
            return sillyFactory.sillyProcessPropertyClass();
        }
        return processPropertyClazz;
    }

    @Override
    protected Class getNodeSourceDataClazz(String category) {
        return nodeSourceDataClazz;
    }

    @Override
    public Class getPropertyHandleClazz(String category) {
        return propertyHandleClazz;
    }

    @Override
    public Class getSillyRootDataClazz(String category) {
        return rootDataClazz;
    }

    @Override
    public SillyReadService getSillyReadService(String category) {
        SillyReadService readService = SillyCoreUtil.consistentOne(category, sillyReadServiceList);
        if (readService == null) {
            readService = getSillyContext(category).registerBean(
                    SillyContext.getSillyReadServiceBeanName(category),
                    defaultReadServiceClazz,
                    bdb -> {
                        SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                        ((BeanDefinitionBuilder) bdb).addPropertyValue("category", category);
                    });
            addSillyReadService(readService);
        }
        return readService;
    }

    @Override
    public SillyWriteService getSillyWriteService(String category) {
        SillyWriteService writeService = SillyCoreUtil.consistentOne(category, sillyWriteServiceList);
        if (writeService == null) {
            writeService = getSillyContext(category).registerBean(
                    SillyContext.getSillyWriteServiceBeanName(category),
                    defaultWriteServiceClazz,
                    bdb -> {
                        SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                        ((BeanDefinitionBuilder) bdb).addPropertyValue("category", category);
                    });
            addSillyWriteService(writeService);
        }
        return writeService;
    }

    @Override
    public SillyEngineService getSillyEngineService(String category) {
        SillyEngineService service = SillyCoreUtil.availableOne(category, sillyEngineServiceList);
        if (service == null) {
            service = getSillyContext(category).registerBean(
                    SillyContext.getSillyEngineServiceBeanName(category),
                    defaultEngineServiceClazz,
                    bdb -> {
                        SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                        ((BeanDefinitionBuilder) bdb).addPropertyValue("category", category);
                    });
            addSillyEngineService(service);
        }
        return service;
    }

    @Override
    public SillyTaskCategoryGroup getSillyTaskCategoryGroup(String category
            , String variableName, String groupName, String userVariableName) {
        return getSillyContext(category).getBeanOrRegister(
                SillyContext.getSillyTaskCategoryGroupBeanName(category, variableName, groupName),
                defaultTaskCategoryGroupClazz,
                bdb -> {
                    SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                    ((BeanDefinitionBuilder) bdb).addPropertyValue("category", category);
                    ((BeanDefinitionBuilder) bdb).addPropertyValue("variableName", variableName);
                    ((BeanDefinitionBuilder) bdb).addPropertyValue("groupName", groupName);
                    ((BeanDefinitionBuilder) bdb).addPropertyValue("userVariableName", userVariableName);
                });
    }

    @Override
    public SillyResumeService getSillyResumeService(String category) {
        SillyResumeService resumeService = SillyCoreUtil.consistentOne(category, sillyResumeServiceList);
        if (resumeService == null) {
            resumeService = getSillyContext(category).registerBean(
                    SillyContext.getSillyResumeServiceBeanName(category),
                    defaultResumeServiceClazz,
                    bdb -> {
                        SillyAssert.isTrue(bdb instanceof BeanDefinitionBuilder, "bdb类型错误" + bdb.getClass());
                        ((BeanDefinitionBuilder) bdb).addPropertyValue("category", category);
                    });
            addSillyResumeService(resumeService);
        }
        return resumeService;
    }

    @Override
    public void init() {
        // 初始化 配置
        initSillyConfig();
        // 初始化其余
        initSillyInitializable();
    }

    protected void initSillyConfig() {
        // 开始初始化配置
        super.init();
        log.info("SillyConfig:" + getClass().getName() + " 初始化完成");
    }

    protected void initSillyInitializable() {
        // 开始初始化配置
        final List beanList = sillyContext.getBeanList(SillyInitializable.class);
        for (SillyInitializable sillyInitializable : beanList) {
            // 不对sillyConfig重新初始化!
            if (!(sillyInitializable instanceof SillyCategoryConfig)) {
                // try catch 预防未知的异常导致项目无法启动(如:RPC执行init() 服务丢失/超时)
                try {
                    sillyInitializable.init();
                } catch (Exception e) {
                    if (e instanceof SillyException) {
                        throw e;
                    }
                    log.warn(sillyInitializable.getClass().getSimpleName() + "初始化异常:" + e.getMessage(), e);
                }

                if (log.isDebugEnabled()) {
                    log.debug("SillyInitializable:" + sillyInitializable.getClass().getName() + " 初始化完成");
                }
            }
        }
    }

    protected boolean threadRefreshFlag = false;

    protected synchronized void initSillyAutoRefresh() {
        boolean autoRefresh = sillyProperties.autoRefresh();
        if (!autoRefresh || threadRefreshFlag) {
            return;
        }

        threadRefreshFlag = true;

        // 线程实时刷新
        new Thread(() -> {
            // 上次加载刷新时间戳
            Long beforeRefreshTime = System.currentTimeMillis();

            Set fileSet = new LinkedHashSet<>();
            List categoryResources = getCategoryResources();
            for (Resource categoryResource : categoryResources) {
                try {
                    if (ResourceUtils.isJarURL(categoryResource.getURL())) {
                        String key = new UrlResource(ResourceUtils.extractJarFileURL(categoryResource.getURL()))
                                .getFile().getPath();
                        fileSet.add(key);
                    } else {
                        fileSet.add(categoryResource.getFile().getPath());
                    }
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
            try {
                // 项目启动后延时 10秒加载配置刷新
                Thread.sleep(10 * 1000);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }

            log.warn("========== 自动热刷新 SillyConfig 线程已开启(生产环境请勿开启) ==========");
            do {
                try {
                    boolean hasModified = false;
                    for (String filePath : fileSet) {
                        File file = new File(filePath);
                        long lastModified = file.lastModified();
                        if (file.isFile() && lastModified > beforeRefreshTime) {
                            hasModified = true;
                        }
                    }
                    if (hasModified) {
                        super.refresh();
                        beforeRefreshTime = System.currentTimeMillis();
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                try {
                    // 间隔 3秒 监控刷新
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }

            } while (true);
        }, "silly Config-Refresh").start();
    }

    protected List getCategoryResources() {
        String[] packagePatternArray = tokenizeToStringArray(processPattern,
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        List resourceList = new ArrayList<>();
        try {
            for (String packagePattern : packagePatternArray) {
                Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(packagePattern);
                for (Resource resource : resources) {
                    resourceList.add(resource);
                }
            }
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
        }
        return resourceList;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy