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.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.iqiny.silly.common.exception.SillyException;
import com.iqiny.silly.common.util.SillyAssert;
import com.iqiny.silly.core.base.SillyContext;
import com.iqiny.silly.core.base.SillyInitializable;
import com.iqiny.silly.core.base.SillyProperties;
import com.iqiny.silly.core.base.core.SillyEntity;
import com.iqiny.silly.core.common.SillyCoreUtil;
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.engine.SillyEngineService;
import com.iqiny.silly.core.group.SillyTaskCategoryGroup;
import com.iqiny.silly.core.savehandle.SillyNodeSourceData;
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.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.core.annotation.Order;
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.*;

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

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

    protected String processPattern;

    Class defaultEngineServiceClazz;

    Class defaultWriteServiceClazz;

    Class defaultReadServiceClazz;

    protected Class nodeSourceDataClazz;

    protected Class processPropertyClazz;

    protected Class propertyHandleClazz;

    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.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() {
        refreshProcessResource();
    }

    /**
     * 加载/刷新傻瓜流程配置资源
     */
    public void refreshProcessResource() {
        List resources = getCategoryResources();
        for (Resource resource : resources) {
            loadSillyProcessProperty(resource);
        }
    }

    protected void loadSillyProcessProperty(Resource resource) {
        if (resource == null || !resource.isReadable()) {
            log.warn(resource == null ? "无数据" : resource.getFilename() + "不可读取,将跳过加载");
            return;
        }
        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();
            String category = fileName.substring(0, fileName.lastIndexOf("."));
            // 按定义顺序生成
            SillyProcessProperty processProperty = JSON.parseObject(json, getProcessPropertyClazz(category), Feature.OrderedField);
            addSillyProcessProperty(category, processProperty);
            log.info("成功更新流程配置文件:" + category);
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
        }
    }

    @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) {
        return processPropertyClazz;
    }

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

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

    @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 void afterPropertiesSet() throws Exception {
        // 初始化 配置
        initSillyConfig();
        // 初始化其余
        initSillyInitializable();
    }

    protected void initSillyConfig() {
        // 开始初始化配置
        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() {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            return Arrays.asList(resolver.getResources(processPattern));
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
        }
        return new ArrayList<>();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy