From e2c592fd4f303351e77fee643ef65d44691e28b8 Mon Sep 17 00:00:00 2001 From: JOETION <1322874562@qq.com> Date: Wed, 20 Jan 2021 18:27:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 18 ++ README.md | 1 + cooperop-base-cache/pom.xml | 32 +++ .../ExtGenericFastJsonRedisSerializer.java | 46 ++++ .../base/cache/redis/RedisConfig.java | 37 +++ .../base/cache/redis/RedisManager.java | 68 ++++++ cooperop-base-datasource/pom.xml | 66 ++++++ .../mysql/common/MultiDataSource.java | 18 ++ .../mysql/config/DruidProperties.java | 121 ++++++++++ .../mysql/config/DynamicDataSource.java | 52 +++++ .../mysql/config/MultiDataSourceAop.java | 76 +++++++ .../mysql/config/MultiDataSourceConfig.java | 33 +++ .../mysql/config/MultiSourceConfig.java | 89 ++++++++ cooperop-base-dictionary/pom.xml | 15 ++ cooperop-base-message/pom.xml | 33 +++ .../base/message/ExternalMessage.java | 28 +++ .../base/message/ExternalMessageImpl.java | 41 ++++ .../base/message/InternalMessage.java | 19 ++ .../base/message/InternalMessageImpl.java | 24 ++ .../message/email/service/EmailService.java | 36 +++ .../email/service/impl/EmailServiceImpl.java | 89 ++++++++ cooperop-base-schedule/pom.xml | 15 ++ cooperop-base-taglib/pom.xml | 15 ++ cooperop-base-workflow/pom.xml | 22 ++ .../snakerflow/SnakerEngineBaseService.java | 37 +++ .../snakerflow/SnakerEngineService.java | 104 +++++++++ .../snakerflow/SnakerEngineServiceImpl.java | 212 ++++++++++++++++++ .../snakerflow/config/BeanConfig.java | 96 ++++++++ pom.xml | 61 +++++ 29 files changed, 1504 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cooperop-base-cache/pom.xml create mode 100644 cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/ExtGenericFastJsonRedisSerializer.java create mode 100644 cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisConfig.java create mode 100644 cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisManager.java create mode 100644 cooperop-base-datasource/pom.xml create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/common/MultiDataSource.java create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DruidProperties.java create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DynamicDataSource.java create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceAop.java create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceConfig.java create mode 100644 cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiSourceConfig.java create mode 100644 cooperop-base-dictionary/pom.xml create mode 100644 cooperop-base-message/pom.xml create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessage.java create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessageImpl.java create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessage.java create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessageImpl.java create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/EmailService.java create mode 100644 cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/impl/EmailServiceImpl.java create mode 100644 cooperop-base-schedule/pom.xml create mode 100644 cooperop-base-taglib/pom.xml create mode 100644 cooperop-base-workflow/pom.xml create mode 100644 cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineBaseService.java create mode 100644 cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineService.java create mode 100644 cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineServiceImpl.java create mode 100644 cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/config/BeanConfig.java create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8a4036 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +target/ +**/target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +*.iml +.idea +modules/log +modules/logs +.project +.settings +.classpath +logs diff --git a/README.md b/README.md new file mode 100644 index 0000000..3d40ee9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +协同办公框架端 \ No newline at end of file diff --git a/cooperop-base-cache/pom.xml b/cooperop-base-cache/pom.xml new file mode 100644 index 0000000..8e4d5fe --- /dev/null +++ b/cooperop-base-cache/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + + business.chaoran + cooperop-demo-base + 1.0-SNAPSHOT + + + business.chaoran + cooperop-base-cache + 1.0-SNAPSHOT + + + + + + com.alibaba + fastjson + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + diff --git a/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/ExtGenericFastJsonRedisSerializer.java b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/ExtGenericFastJsonRedisSerializer.java new file mode 100644 index 0000000..3bb8c51 --- /dev/null +++ b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/ExtGenericFastJsonRedisSerializer.java @@ -0,0 +1,46 @@ +package business.cooperop.base.cache.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +/* + ********************************************** + * DATE PERSON REASON + * 2020-09-27 FXY Created + ********************************************** + */ + +/** + * Fastjson集成 spring-data-redis 扩展 + * + * @author FXY + *

+ * 2018年1月23日 + */ + +public class ExtGenericFastJsonRedisSerializer extends GenericFastJsonRedisSerializer { + + private static int NO_SkipTransientFieldFEATURE; + + { + int features = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.SkipTransientField, false); + NO_SkipTransientFieldFEATURE = SerializerFeature.config(features, SerializerFeature.WriteClassName, true); + } + + @Override + public byte[] serialize(Object object) throws SerializationException { + + if (object == null) { + return new byte[0]; + } + try { + return JSON.toJSONBytes(object, NO_SkipTransientFieldFEATURE); + } catch (Exception ex) { + throw new SerializationException("Could not serialize: " + ex.getMessage(), ex); + } + + } + +} diff --git a/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisConfig.java b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisConfig.java new file mode 100644 index 0000000..a0d9450 --- /dev/null +++ b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisConfig.java @@ -0,0 +1,37 @@ +package business.cooperop.base.cache.redis; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + @Bean + public RedisManager redisManager(RedisTemplate redisTemplate) { + RedisManager redisManager = new RedisManager(); + redisManager.setRedisTemplate(redisTemplate); + return redisManager; + } + + @ConditionalOnMissingBean(RedisTemplate.class) + @Bean("redisTemplate") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate redisTemplate = new RedisTemplate(); + redisTemplate.setConnectionFactory(factory); + + StringRedisSerializer ss = new StringRedisSerializer(); + + //默认使用JdkSerializationRedisSerializer对value进行序列化 + //如果想要保证redis中数据的可读性,可以自定义序列化方式 + ExtGenericFastJsonRedisSerializer redisSerializer = new ExtGenericFastJsonRedisSerializer(); + redisTemplate.setKeySerializer(ss); + redisTemplate.setValueSerializer(redisSerializer); + redisTemplate.setHashKeySerializer(ss); + redisTemplate.setHashValueSerializer(redisSerializer); + return redisTemplate; + } +} diff --git a/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisManager.java b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisManager.java new file mode 100644 index 0000000..4d1f6ee --- /dev/null +++ b/cooperop-base-cache/src/main/java/business/cooperop/base/cache/redis/RedisManager.java @@ -0,0 +1,68 @@ +package business.cooperop.base.cache.redis; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; + +import java.util.concurrent.TimeUnit; + +/** + * RedisManager + * + * @author FXY + *

+ * 2018年1月23日 + */ +public class RedisManager { + + /** + * 默认过期时长,单位:秒 + */ + public final static long DEFAULT_EXPIRE = 60 * 30 * 1; + /** + * 不设置过期时长 + */ + public final static long NOT_EXPIRE = -1; + + private RedisTemplate redisTemplate; + + + public void set(String key, Object value, long expire) { + try { + if (expire == NOT_EXPIRE) { + redisTemplate.opsForValue().set(key, value); + } else { + redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public void set(String key, Object value) { + set(key, value, DEFAULT_EXPIRE); + } + + public T get(String key, Class clazz) { + ValueOperations operations = redisTemplate.opsForValue(); + return operations.get(key); + + } + + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + public void delete(String key) { + redisTemplate.delete(key); + } + + public RedisTemplate getRedisTemplate() { + return redisTemplate; + } + + public void setRedisTemplate(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + +} diff --git a/cooperop-base-datasource/pom.xml b/cooperop-base-datasource/pom.xml new file mode 100644 index 0000000..b5ac697 --- /dev/null +++ b/cooperop-base-datasource/pom.xml @@ -0,0 +1,66 @@ + + + + cooperop-demo-base + business.chaoran + 1.0-SNAPSHOT + + 4.0.0 + + + 3.4.0 + 3.4.0 + 1.18.12 + 1.1.10 + 2.2.7.RELEASE + + + cooperop-base-datasource + + + org.springframework.boot + spring-boot-starter-aop + ${spring-boot.version} + + + + org.springframework.boot + spring-boot-starter-jdbc + ${spring-boot.version} + + + com.baomidou + mybatis-plus-boot-starter + ${mybatisplus-spring-boot-starter.version} + + + + com.baomidou + mybatis-plus-generator + ${mybatisplus.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + com.alibaba + druid + ${druid.version} + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + org.springframework.boot + spring-boot-configuration-processor + ${spring-boot.version} + + + \ No newline at end of file diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/common/MultiDataSource.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/common/MultiDataSource.java new file mode 100644 index 0000000..18b264e --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/common/MultiDataSource.java @@ -0,0 +1,18 @@ +package business.cooperop.base.datasource.mysql.common; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface MultiDataSource { + String name() default "main"; +} \ No newline at end of file diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DruidProperties.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DruidProperties.java new file mode 100644 index 0000000..7ae48a4 --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DruidProperties.java @@ -0,0 +1,121 @@ +package business.cooperop.base.datasource.mysql.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.JdbcConstants; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.sql.SQLException; + +@Component +@ConfigurationProperties(prefix = "spring.datasource") +@Setter +@Getter +@Slf4j +public class DruidProperties { + public DruidProperties() { + log.info("default 数据源加载"); + } + + /** + * 数据源名称 + */ + private String datasourceName = "main"; + + private String url; + + private String username; + + private String password; + /** + * 默认为 MYSQL 8.x 配置 + */ + private String driverClassName; + + private Integer initialSize = 10; + + private Integer minIdle = 3; + + private Integer maxActive = 60; + + private Integer maxWait = 60000; + + private Boolean removeAbandoned = true; + + private Integer removeAbandonedTimeout = 180; + + private Integer timeBetweenEvictionRunsMillis = 60000; + + private Integer minEvictableIdleTimeMillis = 300000; + + private String validationQuery = "SELECT 'x'"; + + private Boolean testWhileIdle = true; + + private Boolean testOnBorrow = false; + + private Boolean testOnReturn = false; + + private Boolean poolPreparedStatements = true; + + private Integer maxPoolPreparedStatementPerConnectionSize = 50; + + private String filters = "stat"; + + public DruidDataSource config() { + DruidDataSource dataSource = new DruidDataSource(); + return config(dataSource); + } + + public DruidDataSource config(DruidDataSource dataSource) { + dataSource.setDbType(JdbcConstants.SQL_SERVER); + dataSource.setUrl(url); + dataSource.setUsername(username); + dataSource.setPassword(password); + dataSource.setDriverClassName(driverClassName); + dataSource.setInitialSize(initialSize); // 定义初始连接数 + dataSource.setMinIdle(minIdle); // 最小空闲 + dataSource.setMaxActive(maxActive); // 定义最大连接数 + dataSource.setMaxWait(maxWait); // 获取连接等待超时的时间 + dataSource.setRemoveAbandoned(removeAbandoned); // 超过时间限制是否回收 + dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout); // 超过时间限制多长 + + // 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + // 配置一个连接在池中最小生存的时间,单位是毫秒 + dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + // 用来检测连接是否有效的sql,要求是一个查询语句 + dataSource.setValidationQuery(validationQuery); + // 申请连接的时候检测 + dataSource.setTestWhileIdle(testWhileIdle); + // 申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能 + dataSource.setTestOnBorrow(testOnBorrow); + // 归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能 + dataSource.setTestOnReturn(testOnReturn); + // 打开PSCache,并且指定每个连接上PSCache的大小 + dataSource.setPoolPreparedStatements(poolPreparedStatements); + dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); + // 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: + // 监控统计用的filter:stat + // 日志用的filter:log4j + // 防御SQL注入的filter:wall + try { + dataSource.setFilters(filters); + } catch (SQLException e) { + log.error("扩展插件失败.{}", e.getMessage()); + } + return dataSource; + } + +} diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DynamicDataSource.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DynamicDataSource.java new file mode 100644 index 0000000..881ad3a --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/DynamicDataSource.java @@ -0,0 +1,52 @@ +package business.cooperop.base.datasource.mysql.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +public class DynamicDataSource extends AbstractRoutingDataSource { + /** + *

多 datasource 的上下文

+ *

每个线程独立的数据库连接名称

+ */ + private static final ThreadLocal contextHolder = new ThreadLocal(); + + /** + * @param dataSourceDbName 数据库别名 + * @Description: 设置数据源别名 + */ + public static void setDataSourceDbName(String dataSourceDbName) { + contextHolder.set(dataSourceDbName); + } + + /** + * @Description: 获取数据源别名 + */ + public static String getDataSourceDbName() { + return contextHolder.get(); + } + + /** + * @Description: 清除数据源别名 + */ + public static void clearDataSourceDbName() { + contextHolder.remove(); + } + + /** + * 重写获取连接名称的方法 + * + * @return 连接名称 + */ + @Override + protected Object determineCurrentLookupKey() { + return getDataSourceDbName(); + } + +} \ No newline at end of file diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceAop.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceAop.java new file mode 100644 index 0000000..5b92120 --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceAop.java @@ -0,0 +1,76 @@ +package business.cooperop.base.datasource.mysql.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import business.cooperop.base.datasource.mysql.common.MultiDataSource; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + + +@Aspect +@Component +@ConditionalOnProperty(prefix = "business.cooperop.base", name = "multiDatasourceOpen", havingValue = "true") +@Slf4j +public class MultiDataSourceAop implements Ordered { + + + public MultiDataSourceAop() { + log.info("多数据源初始化 AOP "); + } + + @Pointcut(value = "@annotation(business.cooperop.base.datasource.mysql.common.MultiDataSource)") + private void cut() { + } + + @Around("cut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + + Signature signature = point.getSignature(); + MethodSignature methodSignature; + if (!(signature instanceof MethodSignature)) { + throw new IllegalArgumentException("该注解只能用于方法"); + } + methodSignature = (MethodSignature) signature; + //获取当前方法的注解 + Object target = point.getTarget(); + Method currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes()); + MultiDataSource datasource = currentMethod.getAnnotation(MultiDataSource.class); + if (datasource != null) { + DynamicDataSource.setDataSourceDbName(datasource.name()); + log.info("设置数据源为:" + datasource.name()); + } else { + DynamicDataSource.setDataSourceDbName("main"); + log.info("设置数据源为:默认 --> main"); + } + try { + return point.proceed(); + } finally { + log.info("清空数据源信息!"); + DynamicDataSource.clearDataSourceDbName(); + } + } + + /** + * aop的顺序要早于spring的事务 + */ + @Override + public int getOrder() { + return 1; + } +} \ No newline at end of file diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceConfig.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceConfig.java new file mode 100644 index 0000000..e98bfd2 --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiDataSourceConfig.java @@ -0,0 +1,33 @@ +package business.cooperop.base.datasource.mysql.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@ConfigurationProperties(prefix = "business.cooperop.base") +@Getter +@Setter +@Slf4j +public class MultiDataSourceConfig { + public MultiDataSourceConfig() { + log.info("加载多数据源配置信息 --> {}", "business.cooperop.base"); + } + + /** + * 多个数据源 + */ + private List datasource; +} diff --git a/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiSourceConfig.java b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiSourceConfig.java new file mode 100644 index 0000000..da547a4 --- /dev/null +++ b/cooperop-base-datasource/src/main/java/business/cooperop/base/datasource/mysql/config/MultiSourceConfig.java @@ -0,0 +1,89 @@ +package business.cooperop.base.datasource.mysql.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020/7/24 FXY Created + ********************************************** + */ + + +import com.alibaba.druid.pool.DruidDataSource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +@Configuration +public class MultiSourceConfig { + + @Autowired + private DruidProperties druidProperties; + + @Autowired + private MultiDataSourceConfig multiDataSourceConfig; + + + /** + * 单数据源连接池配置 + */ + @Bean + @ConditionalOnProperty(name = "business.cooperop.base.multiDatasourceOpen", havingValue = "false") + public DruidDataSource singleDatasource() { + log.info("singleDatasource"); + return druidProperties.config(new DruidDataSource()); + } + + /** + * 多数据源连接池配置 + */ + @Bean + @ConditionalOnProperty(name = "business.cooperop.base.multiDatasourceOpen", havingValue = "true") + public DynamicDataSource mutiDataSource() { + log.info("mutiDataSource"); + + //存储数据源别名与数据源的映射 + HashMap dbNameMap = new HashMap(); + // 核心数据源 + DruidDataSource mainDataSource = druidProperties.config(); + // 这里添加 主要数据库,其它数据库挂了,默认使用主数据库 + dbNameMap.put("main", mainDataSource); + // 其它数据源 + // 当前多数据源是否存在 + if (multiDataSourceConfig.getDatasource() != null) { + //过滤掉没有添加 datasourceName 的数据源,先加载娟全局配置,再次加载当前配置 + List multiDataSourceList = multiDataSourceConfig.getDatasource().stream() + .filter(dp -> !"".equals(Optional.ofNullable(dp.getDatasourceName()).orElse(""))) + .map(dp -> { + DruidDataSource druidDataSource = dp.config(druidProperties.config()); + dbNameMap.put(dp.getDatasourceName(), druidDataSource); + return druidDataSource; + }) + .collect(Collectors.toList()); + + // 测试所有的数据源 + try { + mainDataSource.init(); + for (DruidDataSource druidDataSource : multiDataSourceList) { + druidDataSource.init(); + } + } catch (SQLException sql) { + log.error("======================= 多数据源配置错误 =========================="); + sql.printStackTrace(); + } + } + DynamicDataSource dynamicDataSource = new DynamicDataSource(); + dynamicDataSource.setTargetDataSources(dbNameMap); + dynamicDataSource.setDefaultTargetDataSource(mainDataSource); + return dynamicDataSource; + } + +} \ No newline at end of file diff --git a/cooperop-base-dictionary/pom.xml b/cooperop-base-dictionary/pom.xml new file mode 100644 index 0000000..8b0a70f --- /dev/null +++ b/cooperop-base-dictionary/pom.xml @@ -0,0 +1,15 @@ + + + + cooperop-demo-base + business.chaoran + 1.0-SNAPSHOT + + 4.0.0 + + cooperop-base-dictionary + + + \ No newline at end of file diff --git a/cooperop-base-message/pom.xml b/cooperop-base-message/pom.xml new file mode 100644 index 0000000..eda6977 --- /dev/null +++ b/cooperop-base-message/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + + business.chaoran + cooperop-demo-base + 1.0-SNAPSHOT + + + business.chaoran + cooperop-base-message + 1.0-SNAPSHOT + + + + + + org.projectlombok + lombok + + + + + org.springframework.boot + spring-boot-starter-mail + + + + + diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessage.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessage.java new file mode 100644 index 0000000..5544ec7 --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessage.java @@ -0,0 +1,28 @@ +package business.cooperop.base.message; + +/** + * 外部消息接口 + * @author inaisen + */ +public interface ExternalMessage { + + /** + * 发送手机消息 + */ + void sendMobileMessage(); + + /** + * 发送邮件 + */ + void sendEmailMessage(); + + /** + * 发送微信消息 + */ + void sendWeChartMessage(); + + /** + * 发送钉钉消息 + */ + void sendDingTalkMessage(); +} diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessageImpl.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessageImpl.java new file mode 100644 index 0000000..c9121a7 --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/ExternalMessageImpl.java @@ -0,0 +1,41 @@ +package business.cooperop.base.message; + + +/** + * 外部消息接口实现类 + * @author inaisen + */ +public class ExternalMessageImpl implements ExternalMessage { + + /** + * 发送手机消息实现 + */ + @Override + public void sendMobileMessage() { + + } + + /** + * 发送邮件消息实现 + */ + @Override + public void sendEmailMessage() { + + } + + /** + * 发送微信消息实现 + */ + @Override + public void sendWeChartMessage() { + + } + + /** + * 发送手机钉钉实现 + */ + @Override + public void sendDingTalkMessage() { + + } +} diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessage.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessage.java new file mode 100644 index 0000000..e72a96d --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessage.java @@ -0,0 +1,19 @@ +package business.cooperop.base.message; + +/** + * 内部消息接口 + * @author inaisen + */ +public interface InternalMessage { + + /** + * 设置内部消息接口 + */ + void settingInternalMessage(); + /** + * 查询内部消息接口 + */ + void queryInternalMessage(); + + +} diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessageImpl.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessageImpl.java new file mode 100644 index 0000000..4c6f285 --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/InternalMessageImpl.java @@ -0,0 +1,24 @@ +package business.cooperop.base.message; + +/** + * 内部消息接口实现 + * @author inaisen + */ +public class InternalMessageImpl implements InternalMessage { + + /** + * 设置内部消息 + */ + @Override + public void settingInternalMessage() { + + } + + /** + * 查询内部消息 + */ + @Override + public void queryInternalMessage() { + + } +} diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/EmailService.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/EmailService.java new file mode 100644 index 0000000..cd89280 --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/EmailService.java @@ -0,0 +1,36 @@ +package business.cooperop.base.message.email.service; + +/** + * 天下风云出我辈, 一入代码岁月催 + * + * @Author: deadline + * @Date: 2020-12-22 9:38 + */ +public interface EmailService { + + /** + * 发送文本邮件 + * @param to 收件人 + * @param subject 主题 + * @param content 内容 + */ + void sendSimpleMail(String[] to, String subject, String content); + + /** + * 发送HTML邮件 + * @param to 收件人 + * @param subject 主题 + * @param content 内容 + */ + void sendHtmlMail(String[] to, String subject, String content); + + /** + * 发送带附件的邮件 + * @param to 收件人 + * @param subject 主题 + * @param content 内容 + * @param filePath 附件 + */ + public void sendAttachmentsMail(String[] to, String subject, String content, String...filePath); + +} diff --git a/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/impl/EmailServiceImpl.java b/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/impl/EmailServiceImpl.java new file mode 100644 index 0000000..2f2ac8a --- /dev/null +++ b/cooperop-base-message/src/main/java/business/cooperop/base/message/email/service/impl/EmailServiceImpl.java @@ -0,0 +1,89 @@ +package business.cooperop.base.message.email.service.impl; + +import business.cooperop.base.message.email.service.EmailService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.File; + +/** + * 天下风云出我辈, 一入代码岁月催 + * + * @Author: deadline + * @Date: 2020-12-22 9:38 + */ +@Slf4j +public class EmailServiceImpl implements EmailService { + + @Autowired + private JavaMailSender javaMailSender; + + //注入配置文件中配置的信息——>from + @Value("${spring.mail.from}") + private String from; + + @Override + public void sendSimpleMail(String[] to, String subject, String content) { + SimpleMailMessage message = new SimpleMailMessage(); + //发件人 + message.setFrom(from); + //收件人 + message.setTo(to); + //邮件主题 + message.setSubject(subject); + //邮件内容 + message.setText(content); + //发送邮件 + javaMailSender.send(message); + } + + @Override + public void sendHtmlMail(String[] to, String subject, String content) { + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper messageHelper; + try { + messageHelper = new MimeMessageHelper(message,true); + messageHelper.setFrom(from); + messageHelper.setTo(to); + message.setSubject(subject); + messageHelper.setText(content,true); + javaMailSender.send(message); + log.info("邮件已经发送!"); + } catch (MessagingException e) { + log.error("发送邮件时发生异常:" + e); + } + } + + @Override + public void sendAttachmentsMail(String[] to, String subject, String content, String...filePath) { + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper messageHelper; + try { + messageHelper = new MimeMessageHelper(message,true); + messageHelper.setFrom(from); + messageHelper.setTo(to); + messageHelper.setSubject(subject); + messageHelper.setText(content,true); + + for (String path : filePath) { + //携带附件 + FileSystemResource file = new FileSystemResource(path); + String fileName = path.substring(path.lastIndexOf(File.separator)); + messageHelper.addAttachment(fileName, file); + } + + javaMailSender.send(message); + log.info("邮件加附件发送成功!"); + } catch (MessagingException e) { + log.error("发送失败:"+e); + } + } +} diff --git a/cooperop-base-schedule/pom.xml b/cooperop-base-schedule/pom.xml new file mode 100644 index 0000000..c3f45c6 --- /dev/null +++ b/cooperop-base-schedule/pom.xml @@ -0,0 +1,15 @@ + + + + cooperop-demo-base + business.chaoran + 1.0-SNAPSHOT + + 4.0.0 + + cooperop-base-schedule + + + \ No newline at end of file diff --git a/cooperop-base-taglib/pom.xml b/cooperop-base-taglib/pom.xml new file mode 100644 index 0000000..fe83f81 --- /dev/null +++ b/cooperop-base-taglib/pom.xml @@ -0,0 +1,15 @@ + + + + cooperop-demo-base + business.chaoran + 1.0-SNAPSHOT + + 4.0.0 + + cooperop-base-taglib + + + \ No newline at end of file diff --git a/cooperop-base-workflow/pom.xml b/cooperop-base-workflow/pom.xml new file mode 100644 index 0000000..eccf1f8 --- /dev/null +++ b/cooperop-base-workflow/pom.xml @@ -0,0 +1,22 @@ + + + + cooperop-demo-base + business.chaoran + 1.0-SNAPSHOT + + 4.0.0 + + cooperop-base-workflow + + + com.github.snakerflow-starter + snakerflow-spring-boot-starter + 1.0.3 + + + + + \ No newline at end of file diff --git a/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineBaseService.java b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineBaseService.java new file mode 100644 index 0000000..6f6c7dc --- /dev/null +++ b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineBaseService.java @@ -0,0 +1,37 @@ +package business.cooperop.base.workflow.snakerflow; + +/* + ********************************************** + * DATE PERSON REASON + * 2020-11-25 FXY Created + ********************************************** + */ + + +import org.snaker.engine.SnakerEngine; + +import java.util.List; + +public interface SnakerEngineBaseService { + /** + * 初始化状态机流程 + * + * @return 流程主键 + * @param relativePath + */ + String initFlows(String relativePath); + + /** + * 获得执行引擎 + * + * @return SnakerEngine + */ + SnakerEngine getEngine(); + + /** + * 获得所有流程的名字 + * + * @return List + */ + List getAllProcessNames(); +} diff --git a/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineService.java b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineService.java new file mode 100644 index 0000000..16deaae --- /dev/null +++ b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineService.java @@ -0,0 +1,104 @@ +package business.cooperop.base.workflow.snakerflow; + +/* + ********************************************** + * DATE PERSON REASON + * 2020-11-25 FXY Created + ********************************************** + */ + + +import org.snaker.engine.entity.Order; +import org.snaker.engine.entity.Process; +import org.snaker.engine.entity.Task; + +import java.util.List; +import java.util.Map; + +public interface SnakerEngineService extends SnakerEngineBaseService { + + /** + * 获得所有有效流程 + * + * @return List + */ + List getAllProcess(); + + /** + * 通过orderId 获得流程 + * + * @param orderId 流程实例Id + * @return List + */ + List getProcessByOrderId(String orderId); + + /** + * 通过processId发起一个流程实例 + * + * @param processId 流程ID + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + Order startInstanceById(String processId, String operator, Map args); + + /** + * 通过process name发起一个流程实例 + * + * @param name 流程 name + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + Order startInstanceByName(String name, Integer version, String operator, Map args); + + /** + * 执行流程实例 + * + * @param name 流程 name + * @param version 版本 + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + Order startAndExecute(String name, Integer version, String operator, Map args); + + /** + * 执行流程实例 + * + * @param processId 流程Id + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + Order startAndExecute(String processId, String operator, Map args); + + /** + * 通过taskId执行 + * + * @param taskId 任务Id + * @param operator 操作人 + * @param args 自定义参数 + * @return List + */ + List execute(String taskId, String operator, Map args); + + /** + * 流程跳转 + * + * @param taskId 任务Id + * @param operator 操作人 + * @param args 自定义参数 + * @param nodeName 跳转到的节点名称 + * @return List + */ + List executeAndJump(String taskId, String operator, Map args, String nodeName); + + /** + * 通过orderId获取对应的流程task + * + * @param orderId 流程实例Id + * @return List + */ + List getTasks(String orderId); +} diff --git a/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineServiceImpl.java b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineServiceImpl.java new file mode 100644 index 0000000..b06c66b --- /dev/null +++ b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/SnakerEngineServiceImpl.java @@ -0,0 +1,212 @@ +/* Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package business.cooperop.base.workflow.snakerflow; + +import org.snaker.engine.SnakerEngine; +import org.snaker.engine.access.QueryFilter; +import org.snaker.engine.entity.Order; +import org.snaker.engine.entity.Process; +import org.snaker.engine.entity.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * SnakerEngineFacets封装snakerflow基本操作,可以直接使用 + * + * @author zhaoguoqing + * @since 0.1 + */ +@Component +public class SnakerEngineServiceImpl implements SnakerEngineService { + @Autowired + private SnakerEngine engine; + + /** + * 初始化状态机流程 + * + * @return 流程主键 + * @param relativePath 相对路径 + */ + @Override + public String initFlows(String relativePath) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream stream = classLoader.getResourceAsStream(relativePath); + String deploy = engine.process().deploy(stream); + return deploy; + } + + /** + * 获得所有有效流程 + * + * @return List + */ + @Override + public List getAllProcess() { + QueryFilter filter = new QueryFilter(); + return engine.process().getProcesss(filter); + } + + /** + * 通过orderId 获得流程 + * + * @param orderId 流程实例Id + * @return List + */ + @Override + public List getProcessByOrderId(String orderId) { + QueryFilter filter = new QueryFilter(); + filter.setOrderId(orderId); + return engine.process().getProcesss(filter); + } + + /** + * 获得执行引擎 + * + * @return SnakerEngine + */ + @Override + public SnakerEngine getEngine() { + return engine; + } + + /** + * 获得所有流程的名字 + * + * @return List + */ + @Override + public List getAllProcessNames() { + List list = engine.process().getProcesss(new QueryFilter()); + List names = new ArrayList<>(); + for (Process entity : list) { + if (names.contains(entity.getName())) { + continue; + } else { + names.add(entity.getName()); + } + } + return names; + } + + /** + * 通过processId发起一个流程实例 + * + * @param processId 流程ID + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + @Override + public Order startInstanceById(String processId, String operator, Map args) { + return engine.startInstanceById(processId, operator, args); + } + + /** + * 通过process name发起一个流程实例 + * + * @param name 流程 name + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + @Override + public Order startInstanceByName(String name, Integer version, String operator, Map args) { + return engine.startInstanceByName(name, version, operator, args); + } + + /** + * 执行流程实例 + * + * @param name 流程 name + * @param version 版本 + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + @Override + public Order startAndExecute(String name, Integer version, String operator, Map args) { + Order order = engine.startInstanceByName(name, version, operator, args); + List tasks = engine.query().getActiveTasks(new QueryFilter().setOrderId(order.getId())); + List newTasks = new ArrayList(); + if (tasks != null && tasks.size() > 0) { + Task task = tasks.get(0); + newTasks.addAll(engine.executeTask(task.getId(), operator, args)); + } + return order; + } + + /** + * 执行流程实例 + * + * @param processId 流程Id + * @param operator 操作人 + * @param args 自定义参数 + * @return Order流程实例 + */ + @Override + public Order startAndExecute(String processId, String operator, Map args) { + Order order = engine.startInstanceById(processId, operator, args); + List tasks = engine.query().getActiveTasks(new QueryFilter().setOrderId(order.getId())); + List newTasks = new ArrayList(); + if (tasks != null && tasks.size() > 0) { + Task task = tasks.get(0); + newTasks.addAll(engine.executeTask(task.getId(), operator, args)); + } + return order; + } + + /** + * 通过taskId执行 + * + * @param taskId 任务Id + * @param operator 操作人 + * @param args 自定义参数 + * @return List + */ + @Override + public List execute(String taskId, String operator, Map args) { + return engine.executeTask(taskId, operator, args); + } + + /** + * 流程跳转 + * + * @param taskId 任务Id + * @param operator 操作人 + * @param args 自定义参数 + * @param nodeName 跳转到的节点名称 + * @return List + */ + @Override + public List executeAndJump(String taskId, String operator, Map args, String nodeName) { + return engine.executeAndJumpTask(taskId, operator, args, nodeName); + } + + /** + * 通过orderId获取对应的流程task + * + * @param orderId 流程实例Id + * @return List + */ + @Override + public List getTasks(String orderId) { + return engine.query().getActiveTasks(new QueryFilter().setOrderId(orderId)); + } +} diff --git a/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/config/BeanConfig.java b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/config/BeanConfig.java new file mode 100644 index 0000000..f98971a --- /dev/null +++ b/cooperop-base-workflow/src/main/java/business/cooperop/base/workflow/snakerflow/config/BeanConfig.java @@ -0,0 +1,96 @@ +package business.cooperop.base.workflow.snakerflow.config; + +/* + ********************************************** + * DATE PERSON REASON + * 2020-11-25 FXY Created + ********************************************** + */ + +import org.apache.ibatis.session.SqlSessionFactory; +import org.snaker.engine.DBAccess; +import org.snaker.engine.access.mybatis.MybatisAccess; +import org.snaker.engine.cache.CacheManager; +import org.snaker.engine.cache.memory.MemoryCacheManager; +import org.snaker.engine.core.*; +import org.snaker.engine.impl.LogInterceptor; +import org.snaker.engine.spring.SpelExpression; +import org.snaker.engine.spring.SpringSnakerEngine; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BeanConfig { + + @Bean("engine") + public SpringSnakerEngine springSnakerEngine(ProcessService processService, OrderService orderService, + TaskService taskService, QueryService queryService, ManagerService managerService) { + + SpringSnakerEngine springSnakerEngine = new SpringSnakerEngine(); + springSnakerEngine.setProcessService(processService); + springSnakerEngine.setOrderService(orderService); + springSnakerEngine.setTaskService(taskService); + springSnakerEngine.setQueryService(queryService); + springSnakerEngine.setManagerService(managerService); + return springSnakerEngine; + } + + @Bean + public ProcessService processService(DBAccess dbAccess, CacheManager cacheManager) { + ProcessService processService=new ProcessService(); + processService.setCacheManager(cacheManager); + processService.setAccess(dbAccess); + return processService; + } + + @Bean + public OrderService orderService(DBAccess dbAccess) { + OrderService orderService = new OrderService(); + orderService.setAccess(dbAccess); + return orderService; + } + + @Bean + public TaskService taskService(DBAccess dbAccess) { + TaskService taskService = new TaskService(); + taskService.setAccess(dbAccess); + return taskService; + } + + @Bean + public QueryService queryService(DBAccess dbAccess) { + QueryService queryService = new QueryService(); + queryService.setAccess(dbAccess); + return queryService; + } + + @Bean + public ManagerService managerService(DBAccess dbAccess) { + ManagerService managerService = new ManagerService(); + managerService.setAccess(dbAccess); + return managerService; + } + + @Bean("snakerCacheManager") + public MemoryCacheManager memoryCacheManager(){ + return new MemoryCacheManager(); + } + + @Bean("logInterceptor") + public LogInterceptor logInterceptor(){ + return new LogInterceptor(); + } + + @Bean("spelExpression") + public SpelExpression spelExpression(){ + return new SpelExpression(); + } + + @Bean("dbAccess") + public MybatisAccess mybatisAccess(SqlSessionFactory sqlSessionFactory){ + MybatisAccess mybatisAccess=new MybatisAccess(); + mybatisAccess.setSqlSessionFactory(sqlSessionFactory); + return mybatisAccess; + } + +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1e86f3a --- /dev/null +++ b/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + pom + + + org.springframework.boot + spring-boot-starter-parent + 2.3.2.RELEASE + + + + business.chaoran + cooperop-demo-base + 1.0-SNAPSHOT + + + cooperop-base-datasource + cooperop-base-taglib + cooperop-base-workflow + cooperop-base-dictionary + cooperop-base-message + cooperop-base-cache + cooperop-base-schedule + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + + 1.2.73 + + + + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + + +