├── plasticene-boot-starter-web └── src │ └── main │ ├── resources │ ├── log4j2.component.properties │ ├── META-INF │ │ ├── services │ │ │ └── org.slf4j.spi.SLF4JServiceProvider │ │ ├── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── spring.factories │ └── web-default.properties │ └── java │ └── com │ └── plasticene │ └── boot │ └── web │ ├── core │ ├── constant │ │ ├── ApiSecurityConstant.java │ │ └── ValidatorConstant.java │ ├── advice │ │ ├── NonceChecker.java │ │ ├── ApiSecurityKeyProvider.java │ │ ├── LocalNonceChecker.java │ │ └── DefaultApiSecurityKeyProvider.java │ ├── anno │ │ ├── ApiLog.java │ │ ├── ResponseResultBody.java │ │ ├── FieldMask.java │ │ └── ApiSecurity.java │ ├── validator │ │ ├── CheckEnumValue.java │ │ ├── EnumValue.java │ │ ├── CombineNotNull.java │ │ ├── EnumValueValidator.java │ │ └── CombineNotNullValidator.java │ ├── prop │ │ ├── ApiLogProperties.java │ │ ├── TraceProperties.java │ │ ├── ApiSecurityProperties.java │ │ ├── SwaggerProperties.java │ │ └── ThreadPoolProperties.java │ ├── model │ │ ├── RequestInfo.java │ │ ├── ApiSecurityKey.java │ │ └── ApiSecurityParam.java │ ├── enums │ │ ├── ApiSecurityKeySourceEnum.java │ │ └── MaskEnum.java │ ├── log │ │ └── logback │ │ │ └── TtlLogbackServiceProvider.java │ ├── global │ │ ├── PtcHttpInputMessage.java │ │ └── RequestBodyWrapper.java │ ├── filter │ │ ├── BodyTransferFilter.java │ │ └── WebTraceFilter.java │ ├── utils │ │ ├── IpUtil.java │ │ ├── MDCTraceUtils.java │ │ └── SignUtil.java │ └── interceptor │ │ └── FeignInterceptor.java │ └── autoconfigure │ └── PlasticeneSwaggerAutoConfiguration.java ├── plasticene-boot-example ├── plasticene-boot-banner-example │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── banner │ │ │ │ └── BannerExampleApplication.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── banner │ │ │ └── PlasticeneBootBannerExampleApplicationTests.java │ └── pom.xml ├── plasticene-boot-delay-example │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── application.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── delay │ │ │ │ ├── DelayExampleApplication.java │ │ │ │ └── executor │ │ │ │ └── OrderTaskExecutor.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── delay │ │ │ ├── PlasticeneBootDelayExampleApplicationTests.java │ │ │ └── TestService.java │ └── pom.xml ├── plasticene-boot-redis-example │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── application.yml │ │ └── java │ │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── redis │ │ │ └── RedisExampleApplication.java │ │ └── test │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── example │ │ └── redis │ │ └── PlasticeneBootRedisExampleApplicationTests.java ├── plasticene-boot-web-example │ └── src │ │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── web │ │ │ └── PlasticeneBootWebExampleApplicationTests.java │ │ └── main │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── example │ │ └── web │ │ ├── vo │ │ └── UserVO.java │ │ ├── WebExampleApplication.java │ │ ├── enums │ │ └── GenderEnum.java │ │ └── param │ │ └── UserParam.java ├── plasticene-boot-flow-example │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── flow │ │ │ │ └── PlasticeneBootFlowExampleApplicationTests.java │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── flow │ │ │ │ ├── FlowExampleApplication.java │ │ │ │ └── LeaveFlowInstanceListener.java │ │ │ └── resources │ │ │ └── application.yml │ └── pom.xml ├── plasticene-boot-license-example │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── license │ │ │ │ └── PlasticeneBootLicenseExampleApplicationTests.java │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── plasticene │ │ │ │ └── boot │ │ │ │ └── example │ │ │ │ └── license │ │ │ │ ├── LicenseExampleApplication.java │ │ │ │ ├── controller │ │ │ │ └── TestController.java │ │ │ │ └── processor │ │ │ │ └── LocalLicenseContentProcessor.java │ │ │ └── resources │ │ │ └── application.yml │ └── pom.xml ├── plasticene-boot-mybatis-example │ └── src │ │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── mybatis │ │ │ └── PlasticeneBootMybatisExampleApplicationTests.java │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── plasticene │ │ │ └── boot │ │ │ └── example │ │ │ └── mybatis │ │ │ ├── MybatisExampleApplication.java │ │ │ ├── dao │ │ │ └── UserDAO.java │ │ │ ├── service │ │ │ └── UserService.java │ │ │ └── entity │ │ │ └── User.java │ │ └── resources │ │ └── application.yml └── pom.xml ├── plasticene-boot-starter-flow ├── src │ └── main │ │ ├── resources │ │ ├── META-INF │ │ │ └── spring │ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── mapper │ │ │ └── FlowInstanceMapper.xml │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── flow │ │ ├── core │ │ ├── FlowEngine.java │ │ ├── vo │ │ │ └── FlowProcessVO.java │ │ ├── enums │ │ │ ├── FlowInstanceEventTypeEnum.java │ │ │ ├── FlowConditionTypeEnum.java │ │ │ ├── FlowTaskStatusEnum.java │ │ │ ├── FlowProcessStatusEnum.java │ │ │ ├── FieldTypeEnum.java │ │ │ ├── FlowInstanceStatusEnum.java │ │ │ └── FlowProcessNodeEnum.java │ │ ├── dao │ │ │ ├── FlowTaskDAO.java │ │ │ ├── FlowProcessDAO.java │ │ │ └── FlowInstanceDAO.java │ │ ├── provider │ │ │ ├── FlowTaskAssigneeProvider.java │ │ │ └── DefaultFlowTaskAssigneeProvider.java │ │ ├── param │ │ │ ├── FlowInstanceParam.java │ │ │ ├── FlowTaskParam.java │ │ │ └── FlowProcessParam.java │ │ ├── service │ │ │ ├── FlowProcessService.java │ │ │ ├── FlowRuntimeService.java │ │ │ ├── FlowTaskService.java │ │ │ └── impl │ │ │ │ └── FlowProcessServiceImpl.java │ │ ├── dto │ │ │ ├── ProcessConditionGroup.java │ │ │ ├── ProcessConditionRule.java │ │ │ └── ProcessNodeCondition.java │ │ ├── Test.java │ │ ├── operator │ │ │ ├── NotEqualsOperator.java │ │ │ ├── LessThanOrEqualsOperator.java │ │ │ ├── GreaterThanOrEqualsOperator.java │ │ │ ├── LessThanOperator.java │ │ │ ├── GreaterThanOperator.java │ │ │ └── EqualsOperator.java │ │ ├── event │ │ │ ├── InstanceEvent.java │ │ │ └── BaseFlowInstanceListener.java │ │ ├── factory │ │ │ └── OperatorFactory.java │ │ └── entity │ │ │ ├── FlowProcess.java │ │ │ ├── FlowInstance.java │ │ │ └── FlowTask.java │ │ └── autoconfigure │ │ └── FlowAutoConfiguration.java └── pom.xml ├── plasticene-boot-starter-banner ├── src │ └── main │ │ ├── resources │ │ ├── META-INF │ │ │ └── spring │ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── banner.txt │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── banner │ │ ├── autoconfigure │ │ └── BannerAutoConfiguration.java │ │ └── core │ │ └── BannerApplicationRunner.java └── pom.xml ├── plasticene-boot-starter-delay-queue ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── delay │ │ ├── core │ │ ├── executor │ │ │ └── DelayTaskExecutor.java │ │ ├── coordinator │ │ │ └── Coordinator.java │ │ ├── constant │ │ │ └── DelayConstant.java │ │ ├── storage │ │ │ └── TaskStorage.java │ │ ├── prop │ │ │ └── DelayProperties.java │ │ └── task │ │ │ └── DelayTask.java │ │ └── autoconfigure │ │ └── DelayAutoConfiguration.java └── pom.xml ├── plasticene-boot-starter-license ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── license │ │ ├── core │ │ ├── enums │ │ │ └── VerifySystemType.java │ │ ├── constant │ │ │ └── LicenseConstant.java │ │ ├── processor │ │ │ ├── LicenseExpiryProcessor.java │ │ │ └── LicenseContentProcessor.java │ │ ├── anno │ │ │ └── License.java │ │ ├── param │ │ │ ├── SystemInfo.java │ │ │ ├── CustomKeyStoreParam.java │ │ │ └── LicenseCreatorParam.java │ │ ├── LicenseManagerHolder.java │ │ ├── LicenseCheckApplicationRunner.java │ │ ├── aop │ │ │ └── LicenseAspect.java │ │ ├── schedule │ │ │ └── LicenseTask.java │ │ └── prop │ │ │ └── LicenseProperties.java │ │ ├── autoconfigure │ │ └── LicenseAutoConfiguration.java │ │ └── web │ │ └── LicenseController.java └── pom.xml ├── plasticene-boot-starter-cache ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── cache │ │ └── core │ │ ├── listener │ │ ├── CacheMessage.java │ │ ├── RedisCacheMessageListener.java │ │ └── CaffeineCacheRemovalListener.java │ │ ├── manager │ │ └── CustomRedisCache.java │ │ └── prop │ │ └── MultilevelCacheProperties.java └── pom.xml ├── plasticene-boot-starter-oss ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── oss │ │ └── core │ │ └── prop │ │ └── OssProperties.java └── pom.xml ├── plasticene-boot-starter-redis ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── redis │ │ └── core │ │ ├── resolver │ │ └── IpResolver.java │ │ ├── enums │ │ ├── LockType.java │ │ └── LimitType.java │ │ ├── message │ │ └── AbstractChannelMessage.java │ │ ├── anno │ │ ├── RateLimit.java │ │ └── DistributedLock.java │ │ └── listener │ │ └── AbstractChannelMessageListener.java └── pom.xml ├── plasticene-boot-starter-mybatis ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── mybatis │ │ └── core │ │ ├── enums │ │ └── Algorithm.java │ │ ├── handlers │ │ ├── type │ │ │ ├── StringListTypeHandler.java │ │ │ ├── LongSetTypeHandler.java │ │ │ ├── StringSetTypeHandler.java │ │ │ ├── LongListTypeHandler.java │ │ │ ├── IntegerSetTypeHandler.java │ │ │ ├── IntegerListTypeHandler.java │ │ │ ├── SetTypeHandler.java │ │ │ └── ListTypeHandler.java │ │ ├── TenantDatabaseHandler.java │ │ └── EncryptTypeHandler.java │ │ ├── prop │ │ ├── IdProperties.java │ │ ├── EncryptProperties.java │ │ └── TenantProperties.java │ │ ├── encrypt │ │ ├── EncryptService.java │ │ └── Base64EncryptService.java │ │ ├── metadata │ │ └── BaseDO.java │ │ ├── context │ │ └── TenantContextHolder.java │ │ └── utils │ │ └── MybatisUtils.java └── pom.xml ├── plasticene-boot-starter-excel ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── plasticene │ │ └── boot │ │ └── excel │ │ ├── core │ │ ├── anno │ │ │ └── ExcelExport.java │ │ ├── ReadExcel.java │ │ └── listener │ │ │ └── DataExcelListener.java │ │ ├── autoconfigure │ │ └── PlasticeneExcelAutoConfiguration.java │ │ └── utils │ │ └── ExcelUtil.java └── pom.xml ├── plasticene-common └── src │ └── main │ └── java │ └── com │ └── plasticene │ └── boot │ └── common │ ├── processor │ ├── DataTransformer.java │ └── DataProcessor.java │ ├── constant │ ├── CommonConstant.java │ └── OrderConstant.java │ ├── task │ └── CallbackTask.java │ ├── pojo │ ├── MaskRule.java │ ├── PageResult.java │ └── PageParam.java │ ├── user │ ├── LoginUser.java │ └── RequestUserHolder.java │ ├── enums │ └── ResponseStatusEnum.java │ ├── exception │ └── BizException.java │ ├── utils │ └── PtcBeanUtils.java │ └── aspect │ └── AbstractAspectSupport.java └── plasticene-boot-starter-data-scope └── pom.xml /plasticene-boot-starter-web/src/main/resources/log4j2.component.properties: -------------------------------------------------------------------------------- 1 | log4j2.threadContextMap=com.plasticene.boot.web.core.log.log4j2.TtlThreadContextMap 2 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider: -------------------------------------------------------------------------------- 1 | #com.plasticene.boot.web.core.log.logback.TtlLogbackServiceProvider -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-banner-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=plasticene-boot-banner-example 2 | server.port=8881 -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.flow.autoconfigure.FlowAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8887 3 | 4 | spring: 5 | application: 6 | name: plasticene-boot-delay-example 7 | -------------------------------------------------------------------------------- /plasticene-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.banner.autoconfigure.BannerAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.delay.autoconfigure.DelayAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.license.autoconfigure.LicenseAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.cache.autoconfigure.MultilevelCacheAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-oss/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.plasticene.boot.oss.autoconfigure.OssAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.redis.autoconfigure.PlasticeneRedisAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.mybatis.autoconfigure.PlasticeneMybatisAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.plasticene.boot.excel.autoconfigure.PlasticeneExcelAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/FlowEngine.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core; 2 | 3 | /** 4 | * 工作流引擎顶层核心接口 5 | * @author ZFJ 6 | * @date 2025/9/2 7 | */ 8 | public interface FlowEngine { 9 | } 10 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.plasticene.boot.web.autoconfigure.PlasticeneSwaggerAutoConfiguration 2 | com.plasticene.boot.web.autoconfigure.PlasticeneWebAutoConfiguration -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/vo/FlowProcessVO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/4 8 | */ 9 | @Data 10 | public class FlowProcessVO { 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/resources/web-default.properties: -------------------------------------------------------------------------------- 1 | # jackson 2 | spring.jackson.date-format=yyyy-MM-dd HH:mm:ss 3 | spring.jackson.locale=zh_CN 4 | spring.jackson.time-zone=GMT+8 5 | #设置返回json数据null字段不显示 6 | spring.jackson.default-property-inclusion=non_null 7 | 8 | 9 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowInstanceEventTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/8 6 | */ 7 | public enum FlowInstanceEventTypeEnum { 8 | START, 9 | END 10 | } 11 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/enums/Algorithm.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/7/22 15:41 7 | */ 8 | public enum Algorithm { 9 | BASE64, 10 | AES 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-redis-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8883 3 | 4 | 5 | spring: 6 | data: 7 | redis: 8 | host: 127.0.0.1 9 | port: 6379 10 | database: 0 11 | application: 12 | name: plasticene-boot-redis-example 13 | cache: 14 | type: redis -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/enums/VerifySystemType.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/8/2 10:33 7 | */ 8 | public enum VerifySystemType { 9 | SYSTEM_UUID, 10 | CPU_ID; 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/resolver/IpResolver.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.resolver; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/2 6 | */ 7 | public interface IpResolver { 8 | 9 | /** 10 | * 解析客户端 IP 地址 11 | */ 12 | String resolve(); 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/constant/ApiSecurityConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.constant; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/5/23 7 | */ 8 | public class ApiSecurityConstant { 9 | public static final String API_SECURITY = "api_security"; 10 | } 11 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/constant/LicenseConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.constant; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/7/15 7 | */ 8 | public class LicenseConstant { 9 | 10 | public static final String SYSTEM_INFO = "systemInfo"; 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/constant/ValidatorConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.constant; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/5/23 7 | */ 8 | public class ValidatorConstant { 9 | public static final String VALID_REQUEST_BODY = "valid_request_body"; 10 | } 11 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/advice/NonceChecker.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.advice; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/2 6 | */ 7 | public interface NonceChecker { 8 | /** 9 | * 校验请求标识nonce是否已存在 10 | * 存在返回true,不存在返回false并存储 11 | */ 12 | boolean checkAndStoreNonce(String nonce); 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/enums/LockType.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/7/19 10:47 7 | */ 8 | public enum LockType { 9 | //可重入锁 10 | REENTRANT, 11 | //公平锁 12 | FAIR, 13 | //读锁 14 | READ, 15 | //写锁 16 | WRITE 17 | } 18 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dao/FlowTaskDAO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dao; 2 | 3 | import com.plasticene.boot.flow.core.entity.FlowTask; 4 | import com.plasticene.boot.mybatis.core.mapper.BaseMapperX; 5 | 6 | /** 7 | * @author ZFJ 8 | * @date 2025/9/2 9 | */ 10 | public interface FlowTaskDAO extends BaseMapperX { 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/processor/LicenseExpiryProcessor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.processor; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * license即将到期逻辑处理,如提醒警告 7 | * @author ZFJ 8 | * @date 2025/7/15 9 | */ 10 | public interface LicenseExpiryProcessor { 11 | 12 | void warn(Date expiryDate); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/enums/LimitType.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/7/18 16:56 7 | */ 8 | public enum LimitType { 9 | 10 | /** 11 | * 自定义key 12 | */ 13 | CUSTOM, 14 | 15 | /** 16 | * 请求者IP 17 | */ 18 | IP; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dao/FlowProcessDAO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dao; 2 | 3 | import com.plasticene.boot.flow.core.entity.FlowProcess; 4 | import com.plasticene.boot.mybatis.core.mapper.BaseMapperX; 5 | 6 | /** 7 | * @author ZFJ 8 | * @date 2025/9/2 9 | */ 10 | public interface FlowProcessDAO extends BaseMapperX { 11 | } 12 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/anno/ApiLog.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.anno; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2023/10/31 18:45 9 | */ 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target({ElementType.TYPE, ElementType.METHOD}) 12 | @Documented 13 | public @interface ApiLog { 14 | } 15 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/anno/License.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.anno; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2022/8/3 13:50 9 | */ 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target({ElementType.TYPE, ElementType.METHOD}) 12 | @Documented 13 | public @interface License { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/processor/DataTransformer.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.processor; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2024/9/30 10:19 7 | */ 8 | @FunctionalInterface 9 | public interface DataTransformer { 10 | 11 | /** 12 | * 数据转换 13 | * @param input 14 | * @return 15 | */ 16 | R transform(T input); 17 | } 18 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/provider/FlowTaskAssigneeProvider.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.provider; 2 | 3 | import com.plasticene.boot.flow.core.dto.ProcessNode; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author ZFJ 9 | * @date 2025/9/2 10 | */ 11 | public interface FlowTaskAssigneeProvider { 12 | 13 | List getAssignees(ProcessNode currentNode); 14 | } 15 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-web-example/src/test/java/com/plasticene/boot/example/web/PlasticeneBootWebExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.web; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootWebExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/validator/CheckEnumValue.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.validator; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2025/5/23 9 | */ 10 | public interface CheckEnumValue { 11 | 12 | /** 13 | * 需要校验的枚举类都需要实现该接口返回所有枚举值 14 | * @return 枚举值 15 | */ 16 | List getEnumValue(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-flow-example/src/test/java/com/plasticene/boot/example/flow/PlasticeneBootFlowExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.flow; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootFlowExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/src/test/java/com/plasticene/boot/example/delay/PlasticeneBootDelayExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.delay; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootDelayExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-redis-example/src/test/java/com/plasticene/boot/example/redis/PlasticeneBootRedisExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.redis; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootRedisExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/StringListTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | */ 8 | public class StringListTypeHandler extends ListTypeHandler { 9 | @Override 10 | protected String parseItem(String value) { 11 | return value.trim(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-banner-example/src/test/java/com/plasticene/boot/example/banner/PlasticeneBootBannerExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.banner; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootBannerExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/processor/LicenseContentProcessor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.processor; 2 | 3 | import de.schlichtherle.license.LicenseContent; 4 | 5 | /** 6 | * 在证书安装之后对licenseContent进行业务逻辑处理,比如数据加载,开关判断等等 7 | * @author fjzheng 8 | * @date 2025/7/15 9 | */ 10 | public interface LicenseContentProcessor { 11 | 12 | void process(LicenseContent licenseContent); 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/LongSetTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | */ 8 | public class LongSetTypeHandler extends SetTypeHandler{ 9 | @Override 10 | protected Long parseItem(String value) { 11 | return Long.parseLong(value.trim()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/src/test/java/com/plasticene/boot/example/license/PlasticeneBootLicenseExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.license; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootLicenseExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/test/java/com/plasticene/boot/example/mybatis/PlasticeneBootMybatisExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.mybatis; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PlasticeneBootMybatisExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/param/FlowInstanceParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.param; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author ZFJ 8 | * @date 2025/9/4 9 | */ 10 | @Data 11 | public class FlowInstanceParam { 12 | 13 | @Schema(description = "流程模型id") 14 | private Long processId; 15 | @Schema(description = "业务id") 16 | private Long businessId; 17 | } 18 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/resources/mapper/FlowInstanceMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/prop/IdProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2022/9/1 13:40 10 | */ 11 | @ConfigurationProperties(prefix = "ptc.id") 12 | @Data 13 | public class IdProperties { 14 | private Long datacenter = 0L; 15 | private Long worker = 0L; 16 | } 17 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/anno/ResponseResultBody.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.anno; 2 | 3 | import org.springframework.web.bind.annotation.ResponseBody; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/12 18:36 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.TYPE, ElementType.METHOD}) 14 | @Documented 15 | @ResponseBody 16 | public @interface ResponseResultBody { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/StringSetTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | * 用于处理数据库字段与Java Set类型之间的转换 供项目方使用 8 | */ 9 | @SuppressWarnings("unused") 10 | public class StringSetTypeHandler extends SetTypeHandler { 11 | @Override 12 | protected String parseItem(String value) { 13 | return value.trim(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/advice/ApiSecurityKeyProvider.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.advice; 2 | 3 | import com.plasticene.boot.web.core.model.ApiSecurityKey; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2025/5/23 9 | */ 10 | public interface ApiSecurityKeyProvider { 11 | 12 | /** 13 | * 根据平台标识获取key 14 | * @param appId 第三方应用id 15 | * @return 对应平台的加解密key信息 16 | */ 17 | ApiSecurityKey getApiSecurityKey(String appId); 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/LongListTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | * 用于处理数据库字段与Java List类型之间的转换 供项目方使用 8 | */ 9 | @SuppressWarnings("unused") 10 | public class LongListTypeHandler extends ListTypeHandler{ 11 | @Override 12 | protected Long parseItem(String value) { 13 | return Long.parseLong(value.trim()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dao/FlowInstanceDAO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dao; 2 | 3 | import com.plasticene.boot.flow.core.entity.FlowInstance; 4 | import com.plasticene.boot.mybatis.core.mapper.BaseMapperX; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | /** 8 | * @author ZFJ 9 | * @date 2025/9/2 10 | */ 11 | public interface FlowInstanceDAO extends BaseMapperX { 12 | 13 | FlowInstance selectInstanceForUpdate(@Param("instanceId") Long instanceId); 14 | } 15 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/IntegerSetTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | * 用于处理数据库字段与Java Set类型之间的转换 供项目方使用 8 | */ 9 | @SuppressWarnings("unused") 10 | public class IntegerSetTypeHandler extends SetTypeHandler{ 11 | @Override 12 | protected Integer parseItem(String value) { 13 | return Integer.parseInt(value.trim()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/prop/ApiLogProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2023/10/31 18:55 10 | */ 11 | @Data 12 | @ConfigurationProperties(prefix = "ptc.api.log") 13 | public class ApiLogProperties { 14 | /** 15 | * 是否开启接口日志打印, 默认 16 | */ 17 | private Boolean enable = Boolean.FALSE; 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/IntegerListTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/6/24 7 | * 用于处理数据库字段与Java List类型之间的转换 供项目方使用 8 | */ 9 | @SuppressWarnings("unused") 10 | public class IntegerListTypeHandler extends ListTypeHandler{ 11 | @Override 12 | protected Integer parseItem(String value) { 13 | return Integer.parseInt(value.trim()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/model/RequestInfo.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.model; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 9 | * 请求信息 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2022/7/18 11:29 13 | */ 14 | @Data 15 | public class RequestInfo implements Serializable { 16 | private String ip; 17 | private String url; 18 | private String httpMethod; 19 | private String classMethod; 20 | private Object requestParams; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-flow-example/src/main/java/com/plasticene/boot/example/flow/FlowExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.flow; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author ZFJ 8 | */ 9 | @SpringBootApplication 10 | public class FlowExampleApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(FlowExampleApplication.class, args); 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/encrypt/EncryptService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.encrypt; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/7/22 14:43 7 | */ 8 | public interface EncryptService { 9 | 10 | /** 11 | * 加密算法 12 | * @param content 13 | * @return 14 | */ 15 | String encrypt(String content); 16 | 17 | /** 18 | * 解密算法 19 | * @param content 20 | * @return 21 | */ 22 | String decrypt(String content); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/src/main/java/com/plasticene/boot/example/delay/DelayExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.delay; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author shepherdmy 8 | */ 9 | @SpringBootApplication 10 | public class DelayExampleApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DelayExampleApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-redis-example/src/main/java/com/plasticene/boot/example/redis/RedisExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.redis; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author shepherdmy 8 | */ 9 | @SpringBootApplication 10 | public class RedisExampleApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(RedisExampleApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowConditionTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/2 8 | */ 9 | @Getter 10 | public enum FlowConditionTypeEnum { 11 | AND(1, "AND"), 12 | OR(2, "OR"), 13 | ; 14 | 15 | private final Integer code; 16 | private final String name; 17 | 18 | FlowConditionTypeEnum(Integer code, String name) { 19 | this.code = code; 20 | this.name = name; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/param/FlowTaskParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.param; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.Data; 6 | 7 | /** 8 | * @author ZFJ 9 | * @date 2025/9/5 10 | */ 11 | @Data 12 | public class FlowTaskParam { 13 | @NotNull(message = "taskId不能为空") 14 | @Schema(description = "任务id") 15 | private Long taskId; 16 | @Schema(description = "审批意见") 17 | private String comment; 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/constant/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.constant; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/5 6 | */ 7 | public interface CommonConstant { 8 | 9 | /** 10 | * 开启 是 true 11 | */ 12 | 13 | Integer IS_ON = 1; 14 | /** 15 | * 关闭 否 false 16 | */ 17 | Integer IS_OFF = 0; 18 | 19 | /** 20 | * 已删除 21 | */ 22 | Integer IS_DEL = 1; 23 | 24 | /** 25 | * 未删除 26 | */ 27 | Integer IS_NOT_DEL = 0; 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/message/AbstractChannelMessage.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.message; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2022/9/13 14:47 9 | */ 10 | public abstract class AbstractChannelMessage{ 11 | 12 | /** 13 | * 获得 Redis Channel 14 | * 15 | * @return Channel 16 | */ 17 | @JsonIgnore // 避免序列化。原因是Redis 发布 Channel 消息的时候,已经会指定。 18 | public abstract String getChannel(); 19 | 20 | } -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/executor/DelayTaskExecutor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.executor; 2 | 3 | import com.plasticene.boot.delay.core.task.DelayTask; 4 | 5 | /** 6 | * 延时任务处理器 7 | * @author ZFJ 8 | * @date 2025/10/17 9 | */ 10 | public interface DelayTaskExecutor { 11 | /** 12 | * 执行业务任务处理逻辑 13 | * @param delayedTask 任务 14 | */ 15 | void run(DelayTask delayedTask); 16 | 17 | /** 18 | * 不同业务区分不同队列 19 | * @return 业务队列名称 20 | */ 21 | String queueName(); 22 | } 23 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/model/ApiSecurityKey.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2025/5/23 9 | */ 10 | @Data 11 | public class ApiSecurityKey { 12 | 13 | /** 14 | * 我方rsa私钥 15 | */ 16 | private String rsaPrivateKey; 17 | 18 | /** 19 | * 我方ras公钥 20 | */ 21 | private String rsaPublicKey; 22 | 23 | /** 24 | * 第三方rsa公钥 25 | */ 26 | private String thirdRsaPublicKey; 27 | } 28 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/prop/TraceProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/14 10:12 11 | */ 12 | @Data 13 | @ConfigurationProperties(prefix = "ptc.trace") 14 | public class TraceProperties { 15 | /** 16 | * 是否开启日志链路追踪 17 | */ 18 | private Boolean enable = true; 19 | } 20 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowTaskStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/2 8 | */ 9 | @Getter 10 | public enum FlowTaskStatusEnum { 11 | RUNNING(0, "处理中"), 12 | COMPLETE(1, "已完成"), 13 | REJECT(2, "拒绝"); 14 | 15 | private final Integer code; 16 | private final String name; 17 | 18 | FlowTaskStatusEnum(Integer code, String name) { 19 | this.code = code; 20 | this.name = name; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-banner-example/src/main/java/com/plasticene/boot/example/banner/BannerExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.banner; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author ZFJ 8 | * @date 2025/7/16 9 | */ 10 | @SpringBootApplication 11 | public class BannerExampleApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(BannerExampleApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowProcessStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/2 8 | */ 9 | @Getter 10 | public enum FlowProcessStatusEnum { 11 | 12 | DRAFT(0, "草稿"), 13 | RELEASE(1, "已发布"), 14 | HISTORY(2, "历史"); 15 | 16 | 17 | 18 | private final Integer code; 19 | private final String name; 20 | FlowProcessStatusEnum(Integer code, String name) { 21 | this.code = code; 22 | this.name = name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/processor/DataProcessor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.processor; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2024/9/30 10:28 7 | */ 8 | public class DataProcessor { 9 | public static R processData(T data, DataTransformer transformer) { 10 | return transformer.transform(data); 11 | } 12 | 13 | public static void main(String[] args) { 14 | String s = DataProcessor.processData("hello world", String::toUpperCase); 15 | System.out.println(s); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FieldTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/3 8 | */ 9 | @Getter 10 | public enum FieldTypeEnum { 11 | 12 | STRING(0, "字符串"), 13 | NUMBER(1, "数字"), 14 | DATE(2, "日期"), 15 | COLLECTION(3, "集合"); 16 | 17 | 18 | private final Integer code; 19 | private final String name; 20 | 21 | FieldTypeEnum(Integer code, String name) { 22 | this.code = code; 23 | this.name = name; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowInstanceStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/8 8 | */ 9 | @Getter 10 | public enum FlowInstanceStatusEnum { 11 | RUNNING(0, "审批中"), 12 | APPROVE(1, "审批通过"), 13 | REJECT(2, "审批拒绝") 14 | 15 | ; 16 | 17 | private final Integer code; 18 | private final String name; 19 | 20 | FlowInstanceStatusEnum(Integer code, String name) { 21 | this.code = code; 22 | this.name = name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/java/com/plasticene/boot/excel/core/anno/ExcelExport.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.excel.core.anno; 2 | 3 | import com.alibaba.excel.support.ExcelTypeEnum; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2024/5/7 22:40 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | public @interface ExcelExport { 16 | 17 | String name() default ""; 18 | 19 | String sheet() default "sheet1"; 20 | 21 | ExcelTypeEnum suffix() default ExcelTypeEnum.XLSX; 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/service/FlowProcessService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.plasticene.boot.flow.core.entity.FlowProcess; 5 | import com.plasticene.boot.flow.core.param.FlowProcessParam; 6 | 7 | /** 8 | * @author ZFJ 9 | * @date 2025/9/2 10 | */ 11 | public interface FlowProcessService extends IService { 12 | 13 | 14 | Long createFlowProcess(FlowProcessParam param); 15 | 16 | void updateFlowProcess(FlowProcessParam param); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /plasticene-boot-starter-banner/src/main/java/com/plasticene/boot/banner/autoconfigure/BannerAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.banner.autoconfigure; 2 | 3 | import com.plasticene.boot.banner.core.BannerApplicationRunner; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/12 15:21 11 | */ 12 | @Configuration 13 | public class BannerAutoConfiguration { 14 | @Bean 15 | public BannerApplicationRunner bannerApplicationRunner() { 16 | return new BannerApplicationRunner(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/java/com/plasticene/boot/excel/autoconfigure/PlasticeneExcelAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.excel.autoconfigure; 2 | 3 | import com.plasticene.boot.excel.core.aop.ExcelExportAspect; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2024/5/8 17:39 11 | */ 12 | @Configuration 13 | public class PlasticeneExcelAutoConfiguration { 14 | 15 | 16 | @Bean 17 | public ExcelExportAspect excelExportAspect() { 18 | return new ExcelExportAspect(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/src/main/java/com/plasticene/boot/example/license/LicenseExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.license; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | 7 | /** 8 | * @author shepherd 9 | */ 10 | @SpringBootApplication 11 | @EnableScheduling 12 | public class LicenseExampleApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(LicenseExampleApplication.class, args); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8885 3 | 4 | spring: 5 | application: 6 | name: plasticene-boot-license-example 7 | 8 | 9 | 10 | ptc: 11 | license: 12 | license-path: /Users/shepherdmy/Desktop/license/license.lic 13 | private-keys-store-path: /Users/shepherdmy/Desktop/license/privateKeys.keystore 14 | public-keys-store-path: /Users/shepherdmy/Desktop/license/publicCerts.keystore 15 | verify-system-switch: false 16 | key-pass: she123456 17 | store-pass: she123456 18 | check-cron: 0 0/1 * * * ? 19 | refresh-cron: 0 0/5 * * * ? 20 | # enable: false 21 | 22 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dto/ProcessConditionGroup.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dto; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 条件节点规则组 10 | * @author ZFJ 11 | * @date 2025/9/2 12 | */ 13 | @Data 14 | public class ProcessConditionGroup { 15 | /** 16 | * 条件关系 0:and 1:or 17 | */ 18 | @Schema(description = "条件关系 0:and 1:or") 19 | private Integer type; 20 | 21 | /** 22 | * 多个条件构成一个条件组 23 | */ 24 | @Schema(description = "条件规则集合") 25 | private List conditionRules; 26 | } 27 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/task/CallbackTask.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.task; 2 | 3 | 4 | /** 5 | * @author fjzheng 6 | * @version 1.0 7 | * @date 2024/9/20 11:15 8 | * 回调任务接口 9 | */ 10 | @FunctionalInterface 11 | public interface CallbackTask { 12 | 13 | /** 14 | * 执行任务,接收一个参数返回一个结果 15 | * @param t 16 | * @return 17 | */ 18 | R execute(T t); 19 | 20 | /** 21 | * 任务执行成功回调 22 | * @param result 23 | */ 24 | default void onSuccess(R result) {} 25 | 26 | /** 27 | * 任务执行失败回调 28 | * @param throwable 29 | */ 30 | default void onFailure(Throwable throwable) {}; 31 | } 32 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-flow-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | server: 3 | port: 8886 4 | 5 | 6 | spring: 7 | application: 8 | name: plasticene-boot-flow-example 9 | datasource: 10 | driver-class-name: com.mysql.cj.jdbc.Driver 11 | username: root 12 | password: zfj126289 13 | url: jdbc:mysql://118.178.230.205:23306/ptc_flow?&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&allowMultiQueries=true 14 | main: 15 | allow-circular-references: true 16 | 17 | 18 | logging: 19 | level: 20 | com.plasticene.boot.flow.core.dao: debug 21 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/enums/ApiSecurityKeySourceEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2025/5/23 7 | * 接口参数加解密key的来源方式枚举 8 | */ 9 | public enum ApiSecurityKeySourceEnum { 10 | 11 | /** 12 | * 公共 加解密的key 接口提供方和调用方都共用一个key 13 | * 这是方式可以直接在配置文件配置,简单直接,但是安全性不高 14 | */ 15 | COMMON, 16 | 17 | /** 18 | * 单独 第三方平台调用我方接口,我方会单独为每一个平台生成加解密的公钥秘钥key 19 | * 同时第三方也要也要提供他们自己key供我方进行接口响应结果参数加密返回 20 | * 详见 {@link com.plasticene.boot.web.core.model.ApiSecurityKey} 21 | * 单独的时候,需要业务侧把apiSecurityKey信息作为上下文传递 22 | */ 23 | ALONE; 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/main/java/com/plasticene/boot/example/mybatis/MybatisExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.mybatis; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author shepherd 9 | */ 10 | @SpringBootApplication 11 | @MapperScan(basePackages = "com.plasticene.boot.example.mybatis.dao") 12 | public class MybatisExampleApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(MybatisExampleApplication.class, args); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/enums/MaskEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.enums; 2 | 3 | /** 4 | * @author fjzheng 5 | * @version 1.0 6 | * @date 2022/8/26 16:20 7 | */ 8 | public enum MaskEnum { 9 | /** 10 | * 中文名 11 | */ 12 | CHINESE_NAME, 13 | /** 14 | * 身份证号 15 | */ 16 | ID_CARD, 17 | /** 18 | * 座机号 19 | */ 20 | FIXED_PHONE, 21 | /** 22 | * 手机号 23 | */ 24 | MOBILE_PHONE, 25 | /** 26 | * 地址 27 | */ 28 | ADDRESS, 29 | /** 30 | * 电子邮件 31 | */ 32 | EMAIL, 33 | /** 34 | * 银行卡 35 | */ 36 | BANK_CARD, 37 | 38 | /** 39 | * 秘钥 40 | */ 41 | API_SECRET; 42 | } 43 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/pojo/MaskRule.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.pojo; 2 | 3 | import lombok.Data; 4 | 5 | 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2024/4/30 10:04 11 | */ 12 | @Data 13 | public class MaskRule { 14 | /** 15 | * 字段英文名称 16 | */ 17 | private String name; 18 | /** 19 | * 0:隐藏,1:显示 20 | */ 21 | private Integer type; 22 | /** 23 | * 规则:开头:0 中间:1 末尾: -1 全部: 2 区间:3 24 | */ 25 | private Integer scope; 26 | /** 27 | * 位数 28 | */ 29 | private Integer count; 30 | /** 31 | * 开始位数 32 | */ 33 | private Integer start; 34 | 35 | /** 36 | * 结束位数 37 | */ 38 | private Integer end; 39 | } 40 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | #org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | # com.plasticene.boot.web.autoconfigure.PlasticeneSwaggerAutoConfiguration,\ 3 | # com.plasticene.boot.web.autoconfigure.PlasticeneWebAutoConfiguration 4 | 5 | # 自动配置类EnableAutoConfiguration已经移到META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 6 | # 但应用上下文初始化器、应用监听器...等仍然在该文件spring.factories中,如下示例 7 | #org.springframework.context.ApplicationContextInitializer=\ 8 | # com.plasticene.boot.web.autoconfigure.TtlMDCAdapterInitializer 9 | 10 | #org.springframework.context.ApplicationContextInitializer=\ 11 | #com.example.MyInitializer 12 | # 13 | #org.springframework.context.ApplicationListener=\ 14 | #com.example.MyListener -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/param/SystemInfo.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.param; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/8/1 18:16 11 | */ 12 | @Data 13 | public class SystemInfo implements Serializable { 14 | 15 | /** 16 | * 系统uuid全局唯一 17 | * linux命令:dmidecode -s system-uuid | tr 'A-Z' 'a-z' 18 | */ 19 | private String uuid; 20 | 21 | /** 22 | * 可被允许的CPU序列号 23 | * 24 | * linux命令:dmidecode -t 4 | grep ID |sort -u |awk -F': ' '{print $2}' 25 | */ 26 | private String cpuId; 27 | 28 | /** 29 | * 可被允许的主板序列号 30 | */ 31 | private String mainBoardSerial; 32 | } 33 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/user/LoginUser.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.user; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2022/12/9 01:10 9 | */ 10 | @Data 11 | public class LoginUser { 12 | private Long id; 13 | /** 14 | * 公司id 15 | */ 16 | private Long orgId; 17 | 18 | /** 19 | * 是否是管理员 0:否 1:是 20 | */ 21 | private Integer isAdmin; 22 | 23 | /** 24 | * 姓名 25 | */ 26 | private String name; 27 | 28 | /** 29 | * 性别 0:男 1:女 30 | */ 31 | private Integer gender; 32 | 33 | /** 34 | * 手机号 35 | */ 36 | private String mobile; 37 | 38 | /** 39 | * token令牌 40 | */ 41 | private String token; 42 | } 43 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8884 3 | 4 | 5 | spring: 6 | application: 7 | name: plasticene-boot-mybatis-example 8 | datasource: 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | username: root 11 | password: root 12 | url: jdbc:mysql://127.0.0.1:3306/db_test?&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&allowMultiQueries=true 13 | logging: 14 | level: 15 | com.plasticene.boot.example.mybatis: debug 16 | 17 | ptc: 18 | encrypt: 19 | algorithm: aes 20 | key: plasticene666666 21 | # 必须16位 22 | iv: plasticene666666 23 | 24 | # tenant: 25 | # enable: true 26 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/src/main/java/com/plasticene/boot/example/delay/executor/OrderTaskExecutor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.delay.executor; 2 | 3 | import com.plasticene.boot.delay.core.executor.DelayTaskExecutor; 4 | import com.plasticene.boot.delay.core.task.DelayTask; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author ZFJ 10 | * @date 2025/10/17 11 | */ 12 | @Component 13 | @Slf4j 14 | public class OrderTaskExecutor implements DelayTaskExecutor { 15 | @Override 16 | public void run(DelayTask delayedTask) { 17 | log.info("run delay task {}", delayedTask); 18 | } 19 | 20 | @Override 21 | public String queueName() { 22 | return "order"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/java/com/plasticene/boot/cache/core/listener/CacheMessage.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.cache.core.listener; 2 | 3 | import com.plasticene.boot.redis.core.message.AbstractChannelMessage; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2022/7/20 17:04 13 | */ 14 | @EqualsAndHashCode(callSuper = true) 15 | @Data 16 | public class CacheMessage extends AbstractChannelMessage implements Serializable { 17 | private String cacheName; 18 | private Object key; 19 | private Object value; 20 | private Integer type; 21 | 22 | @Override 23 | public String getChannel() { 24 | return "multilevel-cache-topic"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plasticene-boot-starter-data-scope/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | plasticene-boot-starter-parent 7 | com.plasticene.boot 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | plasticene-boot-starter-data-scope 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/model/ApiSecurityParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2023/5/4 11:17 9 | */ 10 | @Data 11 | public class ApiSecurityParam { 12 | 13 | /** 14 | * 应用id 15 | */ 16 | private String appId; 17 | 18 | /** 19 | * RSA加密后的aes秘钥,需解密 20 | */ 21 | private String key; 22 | 23 | /** 24 | * AES加密的json参数 25 | */ 26 | private String data; 27 | 28 | /** 29 | * 签名 30 | */ 31 | private String sign; 32 | 33 | /** 34 | * 时间戳 35 | */ 36 | private String timestamp; 37 | 38 | /** 39 | * 请求唯一标识 40 | */ 41 | private String nonce; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/prop/ApiSecurityProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2023/4/27 15:04 10 | */ 11 | 12 | @Data 13 | @ConfigurationProperties(prefix = "ptc.api.security") 14 | public class ApiSecurityProperties { 15 | 16 | /** 17 | * 是否开启接口安全验证 18 | */ 19 | private Boolean enable = true; 20 | 21 | /** 22 | * 签名有效时长,单位:秒 23 | */ 24 | private Integer validTime = 60; 25 | 26 | /** 27 | * rsa私钥 28 | */ 29 | private String rsaPrivateKey; 30 | 31 | /** 32 | * rsa公钥 33 | */ 34 | private String rsaPublicKey; 35 | } 36 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-flow-example/src/main/java/com/plasticene/boot/example/flow/LeaveFlowInstanceListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.flow; 2 | 3 | import com.plasticene.boot.flow.core.event.BaseFlowInstanceListener; 4 | import com.plasticene.boot.flow.core.event.InstanceEvent; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author ZFJ 10 | * @date 2025/9/8 11 | */ 12 | @Component 13 | @Slf4j 14 | public class LeaveFlowInstanceListener extends BaseFlowInstanceListener { 15 | @Override 16 | public void doProcessInstanceEvent(InstanceEvent event) { 17 | log.info("======>>>instance event {}", event); 18 | } 19 | 20 | @Override 21 | public String businessType() { 22 | return "wf:leave"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/anno/FieldMask.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.anno; 2 | 3 | import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; 4 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 5 | import com.plasticene.boot.web.core.enums.MaskEnum; 6 | import com.plasticene.boot.web.core.global.MaskSerialize; 7 | 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2022/8/26 16:20 15 | */ 16 | 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @JacksonAnnotationsInside 19 | @JsonSerialize(using = MaskSerialize.class) 20 | public @interface FieldMask { 21 | 22 | /** 23 | * 脱敏类型 24 | * @return 25 | */ 26 | MaskEnum value(); 27 | } 28 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/Test.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/2 6 | */ 7 | public class Test { 8 | 9 | public static void main(String[] args) { 10 | int a = 16; 11 | String s = format(a); 12 | System.out.println(s); 13 | } 14 | 15 | 16 | 17 | 18 | public static String format(Object obj) { 19 | return switch (obj) { 20 | case Integer i -> String.format("int %d", i); 21 | case Long l -> String.format("long %d", l); 22 | case Double d -> String.format("double %f", d); 23 | case String s -> String.format("String %s", s); 24 | case null -> "null"; 25 | default -> obj.toString(); 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/prop/EncryptProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.prop; 2 | 3 | import com.plasticene.boot.mybatis.core.enums.Algorithm; 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/22 15:43 11 | */ 12 | @ConfigurationProperties(prefix = "ptc.encrypt") 13 | @Data 14 | public class EncryptProperties { 15 | /** 16 | * 加密算法 {@link Algorithm} 17 | */ 18 | private Algorithm algorithm = Algorithm.BASE64; 19 | 20 | /** 21 | * aes算法需要秘钥key 22 | */ 23 | private String key = "plasticene666666"; 24 | 25 | /** 26 | * aes算法需要一个偏移量 27 | */ 28 | private String iv = "plasticene666666"; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/java/com/plasticene/boot/cache/core/manager/CustomRedisCache.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.cache.core.manager; 2 | 3 | import org.springframework.data.redis.cache.RedisCache; 4 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 5 | import org.springframework.data.redis.cache.RedisCacheWriter; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/20 17:03 11 | */ 12 | public class CustomRedisCache extends RedisCache { 13 | 14 | /** 15 | * redisCache的构造方法是protected,外部不能调用,所以通过该类来new redisCache 16 | * @param name 17 | * @param cacheWriter 18 | * @param cacheConfig 19 | */ 20 | public CustomRedisCache(String name, RedisCacheWriter cacheWriter, RedisCacheConfiguration cacheConfig) { 21 | super(name, cacheWriter, cacheConfig); 22 | } 23 | } -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-web-example/src/main/java/com/plasticene/boot/example/web/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.web.vo; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2025/5/21 15 | */ 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Builder 19 | @Data 20 | @Schema(description = "用户VO") 21 | public class UserVO { 22 | @Schema(description = "用户id") 23 | private Long userId; 24 | @Schema(description = "姓名") 25 | private String userName; 26 | @Schema(description = "年龄") 27 | private Integer age; 28 | @Schema(description = "出生日期") 29 | private Date birthday; 30 | } 31 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/service/FlowRuntimeService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.plasticene.boot.flow.core.dto.ProcessNode; 5 | import com.plasticene.boot.flow.core.entity.FlowInstance; 6 | import com.plasticene.boot.flow.core.enums.FlowInstanceStatusEnum; 7 | 8 | /** 9 | * @author ZFJ 10 | * @date 2025/9/2 11 | */ 12 | public interface FlowRuntimeService extends IService { 13 | 14 | void startFlowInstanceById(Long processId); 15 | 16 | FlowInstance selectInstanceForUpdate(Long instanceId); 17 | 18 | void updateInstanceCurrentNode(Long instanceId, ProcessNode currentNode); 19 | 20 | void endInstance(FlowInstance instance, ProcessNode currentNode, FlowInstanceStatusEnum status); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/log/logback/TtlLogbackServiceProvider.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.log.logback; 2 | 3 | import ch.qos.logback.classic.LoggerContext; 4 | import ch.qos.logback.classic.spi.LogbackServiceProvider; 5 | import org.slf4j.spi.MDCAdapter; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2025/5/29 11 | */ 12 | public class TtlLogbackServiceProvider extends LogbackServiceProvider { 13 | 14 | private MDCAdapter ttlMdcAdapter; 15 | 16 | @Override 17 | public void initialize() { 18 | super.initialize(); 19 | this.ttlMdcAdapter = TtlLogbackMDCAdapter.getInstance(); 20 | ((LoggerContext)super.getLoggerFactory()).setMDCAdapter(ttlMdcAdapter); 21 | } 22 | 23 | @Override 24 | public MDCAdapter getMDCAdapter() { 25 | return this.ttlMdcAdapter; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/main/java/com/plasticene/boot/example/mybatis/dao/UserDAO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.mybatis.dao; 2 | 3 | import com.plasticene.boot.example.mybatis.entity.User; 4 | import com.plasticene.boot.mybatis.core.mapper.BaseMapperX; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2025/6/24 13 | */ 14 | public interface UserDAO extends BaseMapperX { 15 | 16 | User getById(Long id); 17 | 18 | int batchUpdateByForeach(@Param("userList") List userList); 19 | 20 | int batchUpdateByCaseWhen(@Param("userList") List userList); 21 | 22 | int batchUpdateOnDuplicate(@Param("userList") List userList); 23 | 24 | int batchUpdateReplace(@Param("userList") List userList); 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/src/main/java/com/plasticene/boot/example/license/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.license.controller; 2 | 3 | import com.plasticene.boot.license.core.anno.License; 4 | import io.swagger.v3.oas.annotations.Operation; 5 | import io.swagger.v3.oas.annotations.tags.Tag; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * @author ZFJ 12 | * @date 2025/7/16 13 | */ 14 | @RestController 15 | @RequestMapping("/test") 16 | @Tag(name = "测试license示例") 17 | public class TestController { 18 | 19 | @GetMapping("/anno") 20 | @Operation(summary = "测试license注解校验") 21 | @License 22 | public String testLicense() { 23 | return "success"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-web-example/src/main/java/com/plasticene/boot/example/web/WebExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.web; 2 | 3 | import com.plasticene.boot.example.web.provider.DatabaseApiKeySecurityProvider; 4 | import com.plasticene.boot.web.core.advice.ApiSecurityKeyProvider; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | 9 | /** 10 | * @author fjzheng 11 | */ 12 | @SpringBootApplication 13 | public class WebExampleApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(WebExampleApplication.class, args); 17 | } 18 | 19 | @Bean 20 | public ApiSecurityKeyProvider apiSecurityKeyProvider() { 21 | return new DatabaseApiKeySecurityProvider(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/coordinator/Coordinator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.coordinator; 2 | 3 | import java.util.List; 4 | import java.util.function.BiConsumer; 5 | 6 | /** 7 | * 协调服务接口:注册、注销服务节点,心跳机制,健康检查 8 | * @author ZFJ 9 | * @date 2025/10/16 10 | */ 11 | public interface Coordinator { 12 | 13 | /** 14 | * 服务节点注册 15 | */ 16 | String registerNode(); 17 | 18 | /** 19 | * 注销节点 20 | */ 21 | void unRegisterNode(String nodeId); 22 | 23 | /** 24 | * 获取存活节点 25 | * @return 保活节点 26 | */ 27 | List getActiveNodes(); 28 | 29 | /** 30 | * 心跳续期 31 | */ 32 | void heartBeat(String nodeId); 33 | 34 | /** 35 | * 健康检查 36 | * @param consumer 下线节点任务转移 37 | */ 38 | void checkClusterHealth(BiConsumer, List> consumer); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/user/RequestUserHolder.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.user; 2 | 3 | import com.alibaba.ttl.TransmittableThreadLocal; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2022/12/9 01:16 9 | */ 10 | public class RequestUserHolder { 11 | private static final ThreadLocal userHolder = new TransmittableThreadLocal<>(); 12 | 13 | /** 14 | * 存储用户信息 15 | * 16 | * @param loginUser 17 | */ 18 | public static void add(LoginUser loginUser) { 19 | userHolder.set(loginUser); 20 | } 21 | 22 | /** 23 | * 获取用户信息 24 | * 25 | * @return 26 | */ 27 | public static LoginUser getCurrentUser() { 28 | return userHolder.get(); 29 | } 30 | 31 | /** 32 | * 清除 33 | */ 34 | public static void remove() { 35 | userHolder.remove(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/NotEqualsOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/8 6 | */ 7 | public class NotEqualsOperator extends EqualsOperator implements Operator { 8 | @Override 9 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 10 | try { 11 | boolean compare = super.compare(fieldType, fieldValue, inputValue); 12 | return !compare; 13 | } catch (Exception e) { 14 | // 这里捕获父类抛出的异常返回false,父类已经打印异常了,这里不再重复打印 15 | return false; 16 | } 17 | } 18 | 19 | @Override 20 | public void validate(Integer filedType, String inputValue) { 21 | super.validate(filedType, inputValue); 22 | } 23 | 24 | @Override 25 | public String op() { 26 | return "!="; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/prop/TenantProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | import java.util.Collections; 7 | import java.util.Set; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2022/12/10 18:28 13 | */ 14 | @ConfigurationProperties(prefix = "ptc.tenant") 15 | @Data 16 | public class TenantProperties { 17 | 18 | 19 | /** 20 | * 是否开启多租户功能 21 | */ 22 | private Boolean enable = Boolean.FALSE; 23 | 24 | /** 25 | * 需要忽略多租户的表 26 | * 即默认所有表都开启多租户的功能,所以记得添加对应的 tenant_id 字段哟 27 | */ 28 | private Set ignoreTables = Collections.emptySet(); 29 | 30 | /** 31 | * 需要忽略多租户的请求,例如登录接口这时候还不知道是哪家租户 32 | * */ 33 | private Set ignoreUrls = Collections.emptySet(); 34 | } 35 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/src/main/java/com/plasticene/boot/example/license/processor/LocalLicenseContentProcessor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.license.processor; 2 | 3 | import cn.hutool.core.date.DateUtil; 4 | import com.plasticene.boot.license.core.processor.LicenseContentProcessor; 5 | import de.schlichtherle.license.LicenseContent; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2025/7/15 13 | */ 14 | @Slf4j 15 | @Component 16 | public class LocalLicenseContentProcessor implements LicenseContentProcessor { 17 | @Override 18 | public void process(LicenseContent licenseContent) { 19 | log.info("license content expiry date: {}, extra: {}", 20 | DateUtil.formatDate(licenseContent.getNotAfter()), 21 | licenseContent.getExtra()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/LessThanOrEqualsOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/8 6 | */ 7 | public class LessThanOrEqualsOperator extends GreaterThanOperator implements Operator { 8 | @Override 9 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 10 | try { 11 | boolean compare = super.compare(fieldType, fieldValue, inputValue); 12 | return !compare; 13 | } catch (Exception e) { 14 | // 这里捕获父类抛出的异常返回false,父类已经打印异常了,这里不再重复打印 15 | return false; 16 | } 17 | } 18 | 19 | @Override 20 | public void validate(Integer fieldType, String inputValue) { 21 | super.validate(fieldType, inputValue); 22 | } 23 | 24 | @Override 25 | public String op() { 26 | return "<="; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/GreaterThanOrEqualsOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/9/8 6 | */ 7 | public class GreaterThanOrEqualsOperator extends LessThanOperator implements Operator { 8 | @Override 9 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 10 | try { 11 | boolean compare = super.compare(fieldType, fieldValue, inputValue); 12 | return !compare; 13 | } catch (Exception e) { 14 | // 这里捕获父类抛出的异常返回false,父类已经打印异常了,这里不再重复打印 15 | return false; 16 | } 17 | 18 | } 19 | 20 | @Override 21 | public void validate(Integer fieldType, String inputValue) { 22 | super.validate(fieldType, inputValue); 23 | } 24 | 25 | @Override 26 | public String op() { 27 | return ">="; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/anno/ApiSecurity.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.anno; 2 | 3 | import cn.hutool.core.annotation.Alias; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2023/5/2 11:50 11 | * 12 | * 该注解用于标识 需要经过加密或者加签来加固接口安全性的接口 13 | */ 14 | 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target({ElementType.TYPE, ElementType.METHOD}) 17 | @Documented 18 | public @interface ApiSecurity { 19 | 20 | @Alias("isSign") 21 | boolean value() default true; 22 | 23 | /** 24 | * 是否加签验证,默认开启 25 | * @return 26 | */ 27 | @Alias("value") 28 | boolean isSign() default true; 29 | 30 | /** 31 | * 接口请求参数是否需要解密 32 | * @return 33 | */ 34 | boolean decryptRequest() default false; 35 | 36 | /** 37 | * 接口响应参数是否需要加密 38 | * @return 39 | */ 40 | boolean encryptResponse() default false; 41 | } 42 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/prop/SwaggerProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2022/7/12 17:08 10 | */ 11 | @ConfigurationProperties("swagger-info") 12 | @Data 13 | public class SwaggerProperties { 14 | /** 15 | * 标题 16 | */ 17 | private String title; 18 | /** 19 | * 描述 20 | */ 21 | private String description; 22 | /** 23 | * 作者 24 | */ 25 | private String author; 26 | /** 27 | * 版本 28 | */ 29 | private String version; 30 | /** 31 | * 扫描的包 32 | */ 33 | private String basePackage; 34 | 35 | /** 36 | * url 37 | */ 38 | private String url; 39 | 40 | /** 41 | * 邮箱 42 | */ 43 | private String email; 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/LicenseManagerHolder.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core; 2 | 3 | import de.schlichtherle.license.LicenseManager; 4 | import de.schlichtherle.license.LicenseParam; 5 | 6 | /** 7 | * 双重校验生成LicenseManager单例,但是由于生成和安装、校验的LicenseManager配置不一样 8 | * 所以并不是全局唯一的,所以单例意义不大,安装和验证可以使用同一个LicenseManager 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/28 15:44 12 | */ 13 | public class LicenseManagerHolder { 14 | 15 | private static volatile LicenseManager LICENSE_MANAGER; 16 | 17 | public static LicenseManager getInstance(LicenseParam param){ 18 | if(LICENSE_MANAGER == null){ 19 | synchronized (LicenseManagerHolder.class){ 20 | if(LICENSE_MANAGER == null){ 21 | LICENSE_MANAGER = new LicenseManager(param); 22 | } 23 | } 24 | } 25 | return LICENSE_MANAGER; 26 | } 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/src/test/java/com/plasticene/boot/example/delay/TestService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.delay; 2 | 3 | import com.plasticene.boot.delay.core.DistributedDelayQueue; 4 | import com.plasticene.boot.delay.core.task.DelayTask; 5 | import jakarta.annotation.Resource; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | /** 10 | * @author ZFJ 11 | * @date 2025/10/17 12 | */ 13 | @SpringBootTest 14 | public class TestService { 15 | @Resource 16 | private DistributedDelayQueue distributedDelayQueue; 17 | 18 | @Test 19 | public void test() { 20 | DelayTask task = new DelayTask("order", "001", System.currentTimeMillis() + 3*60*1000); 21 | distributedDelayQueue.addTask(task); 22 | DelayTask task2 = new DelayTask("order", "002", System.currentTimeMillis() + 15*60*1000); 23 | distributedDelayQueue.addTask(task2); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/global/PtcHttpInputMessage.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.global; 2 | 3 | import cn.hutool.core.io.IoUtil; 4 | import org.springframework.http.HttpHeaders; 5 | import org.springframework.http.HttpInputMessage; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * @author fjzheng 12 | * @version 1.0 13 | * @date 2024/7/10 15:32 14 | */ 15 | public class PtcHttpInputMessage implements HttpInputMessage { 16 | private final HttpHeaders headers; 17 | private final String body; 18 | 19 | 20 | 21 | public PtcHttpInputMessage(HttpHeaders headers, String body) { 22 | this.headers = headers; 23 | this.body = body; 24 | } 25 | 26 | @Override 27 | public InputStream getBody() { 28 | return IoUtil.toUtf8Stream(body); 29 | } 30 | 31 | @Override 32 | public HttpHeaders getHeaders() { 33 | return this.headers; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-web-example/src/main/java/com/plasticene/boot/example/web/enums/GenderEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.web.enums; 2 | 3 | import com.plasticene.boot.web.core.validator.CheckEnumValue; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2025/5/23 13 | */ 14 | public enum GenderEnum implements CheckEnumValue { 15 | 16 | MAN(0, "男生"), 17 | WOMAN(1, "女生"); 18 | 19 | private final Integer code; 20 | 21 | private final String name; 22 | 23 | GenderEnum(Integer code, String name) { 24 | this.code = code; 25 | this.name = name; 26 | } 27 | 28 | @Override 29 | public List getEnumValue() { 30 | return Stream.of(GenderEnum.values()) 31 | .map(genderEnum -> genderEnum.code) 32 | .collect(Collectors.toList()); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/constant/DelayConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.constant; 2 | 3 | /** 4 | * @author ZFJ 5 | * @date 2025/10/16 6 | */ 7 | public class DelayConstant { 8 | /** 9 | * 存储分布式集群节点信息 10 | */ 11 | public static final String NODES_KEY = "ptc:nodes"; 12 | /** 13 | * 节点心跳续期key 14 | */ 15 | public static final String NODE_HEARTBEAT_KEY_PREFIX = "ptc:heartbeat:"; 16 | /** 17 | * 集群健康检查分布式锁key 18 | */ 19 | public static final String NODES_HEALTH_KEY = "ptc:nodes:health"; 20 | /** 21 | * 存储业务的任务id 22 | */ 23 | public static final String DELAY_TASK_KEY_PREFIX = "ptc:delay:task:"; 24 | /** 25 | * 存储已执行的任务id 26 | */ 27 | public static final String DELAY_EXECUTED_KEY = "ptc:delay:Executed"; 28 | /** 29 | * 任务执行中的分布式锁key 30 | */ 31 | public static final String DELAY_EXECUTING_KEY_PREFIX = "ptc:delay:executing:"; 32 | } 33 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dto/ProcessConditionRule.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dto; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.Data; 5 | 6 | /** 7 | * 条件规则 8 | * @author ZFJ 9 | * @date 2025/9/2 10 | */ 11 | @Data 12 | public class ProcessConditionRule { 13 | 14 | /** 15 | * 属性字段来源 0:表单 1:系统字段 16 | */ 17 | @Schema(description = "属性字段来源 0:表单 1:系统字段") 18 | private Integer source; 19 | 20 | /** 21 | * 字段 22 | */ 23 | @Schema(description = "字段") 24 | private String field; 25 | 26 | /** 27 | * 字段类型 28 | */ 29 | @Schema(description = "字段类型 0:字符串 1:数字 2:日期 3:bool 4:集合字段") 30 | private Integer type; 31 | 32 | /** 33 | * 运算符 34 | */ 35 | @Schema(description = "运算符") 36 | private String operator; 37 | 38 | /** 39 | * 输入值 40 | */ 41 | @Schema(description = "输入值") 42 | private String inputValue; 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/provider/DefaultFlowTaskAssigneeProvider.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.provider; 2 | 3 | import com.plasticene.boot.flow.core.dto.ProcessNode; 4 | import com.plasticene.boot.flow.core.enums.FlowProcessNodeEnum; 5 | 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Objects; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/2 14 | */ 15 | public class DefaultFlowTaskAssigneeProvider implements FlowTaskAssigneeProvider { 16 | @Override 17 | public List getAssignees(ProcessNode currentNode) { 18 | Integer assigneeType = currentNode.getAssigneeType(); 19 | List assigneeList = currentNode.getAssigneeList(); 20 | if (Objects.equals(assigneeType, FlowProcessNodeEnum.AssigneeType.USER.getCode())) { 21 | return assigneeList; 22 | } 23 | 24 | // todo 其他类型需完善 25 | return Collections.emptyList(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/advice/LocalNonceChecker.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.advice; 2 | 3 | import com.github.benmanes.caffeine.cache.Cache; 4 | import com.github.benmanes.caffeine.cache.Caffeine; 5 | import com.plasticene.boot.web.core.prop.ApiSecurityProperties; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author ZFJ 11 | * @date 2025/9/2 12 | */ 13 | public class LocalNonceChecker implements NonceChecker { 14 | 15 | private final Cache nonceCache; 16 | 17 | public LocalNonceChecker(ApiSecurityProperties apiSecurityProperties) { 18 | this.nonceCache = Caffeine.newBuilder() 19 | .expireAfterWrite(apiSecurityProperties.getValidTime(), TimeUnit.SECONDS) 20 | .build(); 21 | } 22 | 23 | @Override 24 | public boolean checkAndStoreNonce(String nonce) { 25 | // 如果已存在则返回true,否则存储并返回false 26 | return nonceCache.asMap().putIfAbsent(nonce, Boolean.TRUE) != null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/prop/ThreadPoolProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/14 14:55 11 | */ 12 | @Data 13 | @ConfigurationProperties(prefix = "async-tsk") 14 | public class ThreadPoolProperties { 15 | /** 16 | * 线程池维护线程的最小数量. 17 | */ 18 | @Value("${async-task.corePoolSize:10}") 19 | private int corePoolSize; 20 | /** 21 | * 线程池维护线程的最大数量 22 | */ 23 | @Value("${async-task.maxPoolSize:200}") 24 | private int maxPoolSize; 25 | /** 26 | * 队列最大长度 27 | */ 28 | @Value("${async-task.queueCapacity:1000}") 29 | private int queueCapacity; 30 | /** 31 | * 线程池前缀 32 | */ 33 | @Value("${async-task.threadNamePrefix:ptc-pool}") 34 | private String threadNamePrefix; 35 | } 36 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/enums/ResponseStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.enums; 2 | 3 | import cn.hutool.http.HttpStatus; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/12 11:34 11 | */ 12 | @ToString 13 | @Getter 14 | public enum ResponseStatusEnum { 15 | FORBIDDEN(HttpStatus.HTTP_FORBIDDEN, "Forbidden"), 16 | UNAUTHORIZED(HttpStatus.HTTP_UNAUTHORIZED, "Unauthorized"), 17 | SUCCESS(HttpStatus.HTTP_OK, "OK"), 18 | BAD_REQUEST(HttpStatus.HTTP_BAD_REQUEST, "Bad Request"), 19 | SYSTEM_ERROR(HttpStatus.HTTP_INTERNAL_ERROR, "系统异常错误"), 20 | NOT_EXIST(HttpStatus.HTTP_NOT_FOUND, "请求路径不存在"); 21 | 22 | /** 23 | * 业务异常码 24 | */ 25 | private final Integer code; 26 | /** 27 | * 业务异常信息描述 28 | */ 29 | private final String msg; 30 | 31 | ResponseStatusEnum(Integer code, String msg) { 32 | this.code = code; 33 | this.msg = msg; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | plasticene-boot-starter-parent 9 | com.plasticene.boot 10 | ${revision} 11 | 12 | 13 | 14 | plasticene-boot-starter-cache 15 | 16 | 17 | 18 | 19 | 20 | com.plasticene.boot 21 | plasticene-boot-starter-redis 22 | 23 | 24 | 25 | com.github.ben-manes.caffeine 26 | caffeine 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/pojo/PageResult.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2022/7/12 11:43 13 | */ 14 | @Data 15 | public final class PageResult implements Serializable { 16 | 17 | /** 18 | * 数据内容 19 | */ 20 | private List list; 21 | 22 | /** 23 | * 总数 24 | */ 25 | private Long total; 26 | 27 | /** 28 | * 页数 29 | */ 30 | private Long pages; 31 | 32 | 33 | 34 | public PageResult() { 35 | } 36 | 37 | public PageResult(List list, Long total, Long pages) { 38 | this.list = list; 39 | this.total = total; 40 | this.pages = pages; 41 | } 42 | 43 | public PageResult(Long total, Long pages) { 44 | this.list = new ArrayList<>(); 45 | this.total = total; 46 | this.pages = pages; 47 | } 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/dto/ProcessNodeCondition.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.dto; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 流程条件节点 10 | * @author ZFJ 11 | * @date 2025/9/2 12 | */ 13 | 14 | @Data 15 | public class ProcessNodeCondition { 16 | 17 | /** 18 | * 节点key 19 | */ 20 | @Schema(description = "节点key") 21 | private String key; 22 | 23 | /** 24 | * 节点名称 25 | */ 26 | @Schema(description = "节点name") 27 | private String name; 28 | 29 | /** 30 | * 条件组间关系 0:and 1:or 31 | */ 32 | @Schema(description = "条件组间关系 0:and 1:or") 33 | private Integer type; 34 | 35 | /** 36 | * 条件组,一个条件节点包含多个条件组 37 | */ 38 | @Schema(description = "条件组集合") 39 | private List conditionGroups; 40 | 41 | /** 42 | * 子节点 43 | */ 44 | @Schema(description = "条件节点的子节点") 45 | private ProcessNode childNode; 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/advice/DefaultApiSecurityKeyProvider.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.advice; 2 | 3 | import com.plasticene.boot.web.core.model.ApiSecurityKey; 4 | import com.plasticene.boot.web.core.prop.ApiSecurityProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2025/5/23 10 | */ 11 | public class DefaultApiSecurityKeyProvider implements ApiSecurityKeyProvider { 12 | 13 | private final ApiSecurityProperties properties; 14 | 15 | public DefaultApiSecurityKeyProvider(ApiSecurityProperties properties) { 16 | this.properties = properties; 17 | } 18 | 19 | 20 | @Override 21 | public ApiSecurityKey getApiSecurityKey(String appId) { 22 | ApiSecurityKey apiSecurityKey = new ApiSecurityKey(); 23 | apiSecurityKey.setRsaPrivateKey(properties.getRsaPrivateKey()); 24 | apiSecurityKey.setRsaPublicKey(properties.getRsaPublicKey()); 25 | apiSecurityKey.setThirdRsaPublicKey(properties.getRsaPublicKey()); 26 | return apiSecurityKey; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.plasticene.boot 8 | plasticene-boot-starter-parent 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | plasticene-boot-starter-flow 14 | 15 | 16 | 17 | com.plasticene.boot 18 | plasticene-boot-starter-mybatis 19 | 20 | 21 | 22 | com.plasticene.boot 23 | plasticene-boot-starter-web 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.plasticene.boot 8 | plasticene-boot-starter-parent 9 | 2025.3.0 10 | 11 | 12 | plasticene-boot-starter-delay-queue 13 | 14 | 15 | 21 16 | 21 17 | UTF-8 18 | 19 | 20 | 21 | 22 | com.plasticene.boot 23 | plasticene-boot-starter-redis 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/storage/TaskStorage.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.storage; 2 | 3 | import com.plasticene.boot.delay.core.task.DelayTask; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 任务存储接口 9 | * @author ZFJ 10 | * @date 2025/10/16 11 | */ 12 | public interface TaskStorage { 13 | /** 14 | * 新增任务 15 | * @param task 延迟任务 16 | */ 17 | void addTask(DelayTask task); 18 | 19 | /** 20 | * 删除任务 21 | * @param task 延迟任务 22 | */ 23 | void removeTask(DelayTask task); 24 | 25 | /** 26 | * 获取任务数据 27 | */ 28 | List listTask(String queueName, Long startTime, Long endTime); 29 | 30 | /** 31 | * 记录已经执行过的任务 32 | * @param task 延时任务 33 | */ 34 | void addExecutedTask(DelayTask task); 35 | 36 | /** 37 | * 判断当前任务是否执行过 38 | * @param task 延时任务 39 | * @return 执行过标识 40 | */ 41 | boolean isExecuted(DelayTask task); 42 | 43 | /** 44 | * 删除执行过的任务 45 | */ 46 | void removeExecutedTask(Long startTime, Long endTime); 47 | } 48 | -------------------------------------------------------------------------------- /plasticene-boot-starter-banner/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ######## ## ### ###### ######## #### ###### ######## ## ## ######## 2 | ## ## ## ## ## ## ## ## ## ## ## ## ### ## ## 3 | ## ## ## ## ## ## ## ## ## ## #### ## ## 4 | ######## ## ## ## ###### ## ## ## ###### ## ## ## ###### 5 | ## ## ######### ## ## ## ## ## ## #### ## 6 | ## ## ## ## ## ## ## ## ## ## ## ## ### ## 7 | ## ######## ## ## ###### ## #### ###### ######## ## ## ######## 8 | 9 | ███╗ ██╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗ 10 | ████╗ ██║██╔═══██╗ ██╔══██╗██║ ██║██╔════╝ 11 | ██╔██╗ ██║██║ ██║ ██████╔╝██║ ██║██║ ███╗ 12 | ██║╚██╗██║██║ ██║ ██╔══██╗██║ ██║██║ ██║ 13 | ██║ ╚████║╚██████╔╝ ██████╔╝╚██████╔╝╚██████╔╝ 14 | 15 | Application Name: ${spring.application.name} Spring Boot Version: ${spring-boot.version} -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/java/com/plasticene/boot/cache/core/listener/RedisCacheMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.cache.core.listener; 2 | 3 | import com.plasticene.boot.redis.core.listener.AbstractChannelMessageListener; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.cache.caffeine.CaffeineCache; 8 | 9 | 10 | import java.util.Objects; 11 | 12 | /** 13 | * @author fjzheng 14 | * @version 1.0 15 | * @date 2022/7/20 17:13 16 | */ 17 | @EqualsAndHashCode(callSuper = true) 18 | @Slf4j 19 | @Data 20 | public class RedisCacheMessageListener extends AbstractChannelMessageListener { 21 | 22 | private CaffeineCache caffeineCache; 23 | 24 | @Override 25 | public void onMessage(CacheMessage message) { 26 | log.info("监听的redis message: {}", message.toString()); 27 | // key为空,代表clear()清除所有key 28 | if (Objects.isNull(message.getKey())) { 29 | caffeineCache.invalidate(); 30 | } else { 31 | caffeineCache.evict(message.getKey()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/validator/EnumValue.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.validator; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | import static java.lang.annotation.ElementType.*; 11 | import static java.lang.annotation.ElementType.TYPE_USE; 12 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2025/5/23 18 | */ 19 | @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) 20 | @Retention(RUNTIME) 21 | @Documented 22 | @Constraint(validatedBy = {EnumValueValidator.class}) 23 | public @interface EnumValue { 24 | 25 | String message() default "enum value is not valid"; 26 | 27 | /** 关联的枚举类 */ 28 | Class linkEnum() default CheckEnumValue.class; 29 | 30 | Class[] groups() default { }; 31 | 32 | Class[] payload() default { }; 33 | } 34 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/exception/BizException.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.exception; 2 | 3 | 4 | import com.plasticene.boot.common.enums.ResponseStatusEnum; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | import java.text.MessageFormat; 9 | 10 | /** 11 | * 业务异常类 12 | * @author shepherdmy 13 | */ 14 | @EqualsAndHashCode(callSuper = true) 15 | @Data 16 | public class BizException extends RuntimeException { 17 | 18 | private Integer code; 19 | 20 | public BizException() { 21 | super(); 22 | } 23 | 24 | public BizException(String message) { 25 | super(message); 26 | } 27 | 28 | public BizException(String pattern, Object... args) { 29 | super(MessageFormat.format(pattern, args)); 30 | } 31 | 32 | public BizException(Integer code, String message) { 33 | super(message); 34 | this.code = code; 35 | } 36 | 37 | public BizException(ResponseStatusEnum responseStatusEnum) { 38 | super(responseStatusEnum.getMsg()); 39 | this.code = responseStatusEnum.getCode(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/event/InstanceEvent.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.event; 2 | 3 | import com.plasticene.boot.flow.core.dto.ProcessNode; 4 | import com.plasticene.boot.flow.core.entity.FlowInstance; 5 | import com.plasticene.boot.flow.core.enums.FlowInstanceEventTypeEnum; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import org.springframework.context.ApplicationEvent; 9 | 10 | /** 11 | * 流程实例事件 12 | * @author ZFJ 13 | * @date 2025/9/8 14 | */ 15 | @Getter 16 | @Setter 17 | public class InstanceEvent extends ApplicationEvent { 18 | /** 19 | * 当前审批流程实例 20 | */ 21 | private FlowInstance instance; 22 | /** 23 | * 业务id 24 | */ 25 | private Long businessId; 26 | 27 | /** 28 | * 流程分类 = 业务分类 29 | */ 30 | private String category; 31 | /** 32 | * 当前节点信息 33 | */ 34 | private ProcessNode currentNode; 35 | 36 | /** 37 | * 事件类型 38 | */ 39 | private FlowInstanceEventTypeEnum eventType; 40 | 41 | 42 | public InstanceEvent(Object source) { 43 | super(source); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-web-example/src/main/java/com/plasticene/boot/example/web/param/UserParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.web.param; 2 | 3 | import com.plasticene.boot.example.web.enums.GenderEnum; 4 | import com.plasticene.boot.web.core.validator.CombineNotNull; 5 | import com.plasticene.boot.web.core.validator.EnumValue; 6 | import io.swagger.v3.oas.annotations.media.Schema; 7 | import jakarta.validation.constraints.NotBlank; 8 | import lombok.Data; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * @author fjzheng 14 | * @version 1.0 15 | * @date 2025/5/21 16 | */ 17 | @Data 18 | @Schema(description = "用户参数") 19 | public class UserParam { 20 | @Schema(description = "用户id") 21 | private Long id; 22 | @Schema(description = "用户姓名") 23 | @NotBlank(message = "名字不能为空") 24 | private String name; 25 | @Schema(description = "用户性别") 26 | @EnumValue(message = "性别枚举值不对", linkEnum = GenderEnum.class) 27 | private Integer gender; 28 | @Schema(description = "用户出生日期") 29 | @CombineNotNull(message = "女生出生日期不能为空", condition = "#this.gender == 1") 30 | private Date birthday; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/service/FlowTaskService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.service; 2 | 3 | import com.plasticene.boot.flow.core.dto.ProcessNode; 4 | import com.plasticene.boot.flow.core.dto.ProcessNodeCondition; 5 | import com.plasticene.boot.flow.core.entity.FlowInstance; 6 | import com.plasticene.boot.flow.core.param.FlowTaskParam; 7 | 8 | /** 9 | * @author ZFJ 10 | * @date 2025/9/2 11 | */ 12 | public interface FlowTaskService { 13 | 14 | void createStartTask(FlowInstance instance, ProcessNode currentNode); 15 | 16 | void createApproveTask(FlowInstance instance, ProcessNode currentNode); 17 | 18 | void createCopyTask(FlowInstance instance, ProcessNode currentNode); 19 | 20 | void createEndTask(FlowInstance instance, ProcessNode currentNode); 21 | 22 | void createConditionBranchTask(FlowInstance instance, ProcessNode currentNode); 23 | 24 | void createConditionNodeTask(FlowInstance instance, ProcessNodeCondition conditionNode); 25 | 26 | void approveTask(FlowTaskParam param); 27 | 28 | void rejectTask(FlowTaskParam param); 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/prop/DelayProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author ZFJ 8 | * @date 2025/10/16 9 | */ 10 | @Data 11 | @ConfigurationProperties(prefix = "ptc.delay") 12 | public class DelayProperties { 13 | /** 14 | * 节点心跳续期保活周期,单位:秒,默认30s 15 | */ 16 | private Integer heartbeatPeriod = 30; 17 | /** 18 | * 拉取数据初始化延迟时间,单位:秒,默认0s 19 | */ 20 | private Integer pullInitialDelay = 0; 21 | /** 22 | * 拉取数据的周期,单位:秒,默认10m 23 | */ 24 | private Integer pullPeriod = 10*60; 25 | /** 26 | * 健康检查初始化延迟时间,单位:秒,默认2m 27 | */ 28 | private Integer healthInitialDelay = 2*60; 29 | /** 30 | * 健康检查周期,单位:秒,默认3m 31 | */ 32 | private Integer healthPeriod = 3*60; 33 | /** 34 | * 删除数据的初始化延迟时间,单位:秒,默认1h 35 | */ 36 | private Integer removeInitialDelay = 60*60; 37 | /** 38 | * 删除数据周期,单位:秒,默认1h 39 | */ 40 | private Integer removePeriod = 60*60; 41 | } 42 | -------------------------------------------------------------------------------- /plasticene-boot-starter-banner/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.plasticene.boot 9 | plasticene-boot-starter-parent 10 | ${revision} 11 | ../pom.xml 12 | 13 | 14 | plasticene-boot-starter-banner 15 | 16 | 17 | 18 | 19 | 20 | com.plasticene.boot 21 | plasticene-common 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-actuator-autoconfigure 27 | true 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /plasticene-boot-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.plasticene.boot 8 | plasticene-boot-starter-parent 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | plasticene-boot-example 14 | pom 15 | 16 | 17 | plasticene-boot-banner-example 18 | plasticene-boot-web-example 19 | plasticene-boot-redis-example 20 | plasticene-boot-mybatis-example 21 | plasticene-boot-license-example 22 | plasticene-boot-flow-example 23 | plasticene-boot-delay-example 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/encrypt/Base64EncryptService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.encrypt; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Base64; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/22 14:46 12 | */ 13 | @Slf4j 14 | public class Base64EncryptService implements EncryptService { 15 | @Override 16 | public String encrypt(String content) { 17 | try { 18 | return Base64.getEncoder().encodeToString(content.getBytes(StandardCharsets.UTF_8)); 19 | } catch (Exception e) { 20 | log.error("base64 encrypt error: ", e); 21 | } 22 | return content; 23 | } 24 | 25 | @Override 26 | public String decrypt(String content) { 27 | try { 28 | byte[] asBytes = Base64.getDecoder().decode(content); 29 | return new String(asBytes, StandardCharsets.UTF_8); 30 | } catch (Exception e) { 31 | log.error("base64 decrypt error: ", e); 32 | } 33 | return content; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/filter/BodyTransferFilter.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.filter; 2 | 3 | import com.plasticene.boot.web.core.global.RequestBodyWrapper; 4 | import jakarta.servlet.*; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.io.IOException; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2023/5/4 23:23 15 | */ 16 | @Slf4j 17 | public class BodyTransferFilter implements Filter { 18 | @Override 19 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 20 | RequestBodyWrapper requestBodyWrapper = null; 21 | try { 22 | HttpServletRequest req = (HttpServletRequest)request; 23 | requestBodyWrapper = new RequestBodyWrapper(req); 24 | 25 | }catch (Exception e){ 26 | log.warn("requestBodyWrapper Error:", e); 27 | } 28 | chain.doFilter((Objects.isNull(requestBodyWrapper) ? request : requestBodyWrapper), response); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plasticene-boot-starter-oss/src/main/java/com/plasticene/boot/oss/core/prop/OssProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.oss.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2023/4/20 10:57 10 | */ 11 | @Data 12 | @ConfigurationProperties(prefix = "oss") 13 | public class OssProperties { 14 | /** 15 | * 对象存储服务的URL 16 | */ 17 | private String endpoint; 18 | 19 | /** 20 | * 区域 21 | */ 22 | private String region; 23 | 24 | /** 25 | * true path-style nginx 反向代理和S3默认支持 pathStyle模式 {http://endpoint/bucketname} 26 | * false supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style 模式{http://bucketname.endpoint} 27 | * 只是url的显示不一样 28 | */ 29 | private Boolean pathStyleAccess = true; 30 | 31 | /** 32 | * Access key 33 | */ 34 | private String accessKey; 35 | 36 | /** 37 | * Secret key 38 | */ 39 | private String secretKey; 40 | 41 | /** 42 | * 最大线程数,默认: 100 43 | */ 44 | private Integer maxConnections = 100; 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/param/CustomKeyStoreParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.param; 2 | 3 | import de.schlichtherle.license.AbstractKeyStoreParam; 4 | import lombok.*; 5 | 6 | import java.io.*; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/28 14:39 12 | */ 13 | @Getter 14 | @Setter 15 | public class CustomKeyStoreParam extends AbstractKeyStoreParam { 16 | 17 | /** 18 | * 公钥/私钥在磁盘上的存储路径 19 | */ 20 | private String storePath; 21 | private String alias; 22 | private String storePwd; 23 | private String keyPwd; 24 | 25 | 26 | public CustomKeyStoreParam(Class clazz, String resource,String alias,String storePwd,String keyPwd) { 27 | super(clazz, resource); 28 | this.storePath = resource; 29 | this.alias = alias; 30 | this.storePwd = storePwd; 31 | this.keyPwd = keyPwd; 32 | } 33 | 34 | /** 35 | * 用于将公私钥存储文件存放到其他磁盘位置而不是项目中 36 | * @return java.io.InputStream 37 | */ 38 | @Override 39 | public InputStream getStream() throws IOException { 40 | return new FileInputStream(storePath); 41 | } 42 | } -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/validator/CombineNotNull.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.validator; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import org.intellij.lang.annotations.Language; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.Target; 10 | 11 | import static java.lang.annotation.ElementType.*; 12 | import static java.lang.annotation.ElementType.TYPE_USE; 13 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2025/5/23 19 | */ 20 | @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) 21 | @Retention(RUNTIME) 22 | @Documented 23 | @Constraint(validatedBy = {CombineNotNullValidator.class}) 24 | public @interface CombineNotNull { 25 | String message() default "enum value is not valid"; 26 | 27 | /** Spring SpEL表达式 */ 28 | @Language("SpEL") 29 | String condition() default ""; 30 | 31 | 32 | Class[] groups() default { }; 33 | 34 | Class[] payload() default { }; 35 | } 36 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/autoconfigure/FlowAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.autoconfigure; 2 | 3 | import com.plasticene.boot.flow.core.executor.ProcessInstanceExecutor; 4 | import com.plasticene.boot.flow.core.provider.DefaultFlowTaskAssigneeProvider; 5 | import com.plasticene.boot.flow.core.provider.FlowTaskAssigneeProvider; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.ComponentScan; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/3 14 | */ 15 | @Configuration 16 | @ComponentScan(basePackages = {"com.plasticene.boot.flow"}) 17 | @MapperScan(basePackages = {"com.plasticene.boot.flow.core.dao"}) 18 | public class FlowAutoConfiguration { 19 | 20 | @Bean 21 | public FlowTaskAssigneeProvider flowTaskAssigneeProvider () { 22 | return new DefaultFlowTaskAssigneeProvider(); 23 | } 24 | 25 | @Bean 26 | public ProcessInstanceExecutor processInstanceExecutor () { 27 | return new ProcessInstanceExecutor(); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/metadata/BaseDO.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.metadata; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableLogic; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.Date; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2022/7/12 10:35 15 | */ 16 | 17 | /** 18 | * 数据库表字段公共属性抽象类 19 | */ 20 | @Data 21 | public class BaseDO implements Serializable { 22 | /** 23 | * 创建时间 24 | */ 25 | @TableField(fill = FieldFill.INSERT) 26 | private Date createTime; 27 | /** 28 | * 最后更新时间 29 | */ 30 | @TableField(fill = FieldFill.INSERT_UPDATE) 31 | private Date updateTime; 32 | /** 33 | * 创建者 34 | */ 35 | @TableField(fill = FieldFill.INSERT) 36 | private Long creator; 37 | /** 38 | * 更新者 39 | */ 40 | @TableField(fill = FieldFill.INSERT_UPDATE) 41 | private Long updater; 42 | /** 43 | * 是否删除 44 | */ 45 | // @TableLogic 46 | // private Integer deleted; 47 | } -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/anno/RateLimit.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.anno; 2 | 3 | import com.plasticene.boot.redis.core.enums.LimitType; 4 | 5 | import java.lang.annotation.*; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/18 16:55 12 | */ 13 | @Target({ElementType.METHOD, ElementType.TYPE}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Inherited 16 | @Documented 17 | public @interface RateLimit { 18 | 19 | /** 20 | * 分区名字,按照业务类型区分,比如用户服务→user,商品服务→product 21 | */ 22 | String name() default ""; 23 | 24 | /** 25 | * key 26 | */ 27 | String key() default ""; 28 | 29 | /** 30 | * 给定的时间范围 默认单位(秒) 31 | */ 32 | int period(); 33 | 34 | /** 35 | * Key的前缀 36 | */ 37 | String prefix() default ""; 38 | 39 | /** 40 | * 时间单位 41 | */ 42 | TimeUnit unit() default TimeUnit.SECONDS; 43 | 44 | /** 45 | * 一定时间内最多访问次数 46 | */ 47 | int count(); 48 | 49 | /** 50 | * 限流的类型(用户自定义key 或者 请求ip,默认为自定义key) 51 | */ 52 | LimitType limitType() default LimitType.CUSTOM; 53 | } 54 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/pojo/PageParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.pojo; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.Data; 7 | 8 | 9 | import java.util.Objects; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2022/7/12 11:44 15 | */ 16 | @Data 17 | public class PageParam { 18 | private static final Integer PAGE_NO = 1; 19 | private static final Integer PAGE_SIZE = 20; 20 | 21 | @NotNull(message = "页码不能为空") 22 | @Min(value = 1, message = "页码最小值为 1") 23 | private Integer pageNo = PAGE_NO; 24 | 25 | @NotNull(message = "每页条数不能为空") 26 | @Min(value = 1, message = "页码最小值为 1") 27 | @Max(value = 2000, message = "页码最大值为 2000") 28 | private Integer pageSize = PAGE_SIZE; 29 | 30 | public PageParam() { 31 | 32 | } 33 | 34 | public PageParam(Integer pageNo, Integer pageSize) { 35 | if (Objects.nonNull(pageNo)) { 36 | this.pageNo = pageNo; 37 | } 38 | if (Objects.nonNull(pageSize)) { 39 | this.pageSize = pageSize; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | plasticene-boot-starter-parent 9 | com.plasticene.boot 10 | ${revision} 11 | 12 | 13 | 14 | plasticene-boot-starter-redis 15 | 16 | 17 | 18 | 19 | 20 | 21 | com.plasticene.boot 22 | plasticene-common 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-data-redis 28 | 29 | 30 | 31 | org.redisson 32 | redisson 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/factory/OperatorFactory.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.factory; 2 | 3 | import com.plasticene.boot.flow.core.operator.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.function.Function; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/3 14 | */ 15 | public class OperatorFactory { 16 | 17 | private static final List OPERATOR_LIST = new ArrayList<>(); 18 | 19 | private static final Map OPERATOR_MAP; 20 | 21 | static { 22 | OPERATOR_LIST.add(new EqualsOperator()); 23 | OPERATOR_LIST.add(new NotEqualsOperator()); 24 | OPERATOR_LIST.add(new LessThanOperator()); 25 | OPERATOR_LIST.add(new LessThanOrEqualsOperator()); 26 | OPERATOR_LIST.add(new GreaterThanOperator()); 27 | OPERATOR_LIST.add(new GreaterThanOrEqualsOperator()); 28 | 29 | 30 | 31 | OPERATOR_MAP = OPERATOR_LIST.stream() 32 | .collect(Collectors.toMap(Operator::op, Function.identity())); 33 | } 34 | 35 | public static Operator getOperator(String op) { 36 | return OPERATOR_MAP.get(op); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/utils/PtcBeanUtils.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.BeanUtils; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/8/17 16:21 11 | */ 12 | public class PtcBeanUtils { 13 | 14 | private static Logger log = LoggerFactory.getLogger(PtcBeanUtils.class); 15 | 16 | public static B copy(A a, Class clazz) { 17 | if (a == null || clazz == null) { 18 | return null; 19 | } 20 | 21 | try { 22 | B b = clazz.newInstance(); 23 | BeanUtils.copyProperties(a, b); 24 | return b; 25 | } catch (Exception e) { 26 | log.error("PtcBeanUtils#copy error.", e); 27 | } 28 | return null; 29 | } 30 | 31 | public static B copy(A a, B b) { 32 | if (a == null || b == null) { 33 | return null; 34 | } 35 | 36 | try { 37 | BeanUtils.copyProperties(a, b); 38 | return b; 39 | } catch (Exception e) { 40 | log.error("PtcBeanUtils#copy error.", e); 41 | } 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/java/com/plasticene/boot/cache/core/listener/CaffeineCacheRemovalListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.cache.core.listener; 2 | 3 | import com.github.benmanes.caffeine.cache.RemovalCause; 4 | import com.github.benmanes.caffeine.cache.RemovalListener; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.lang.NonNull; 7 | import org.springframework.lang.Nullable; 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2022/7/20 17:12 13 | */ 14 | @Slf4j 15 | public class CaffeineCacheRemovalListener implements RemovalListener { 16 | @Override 17 | public void onRemoval(@Nullable Object k, @Nullable Object v, @NonNull RemovalCause cause) { 18 | log.info("[移除缓存] key:{} reason:{}", k, cause.name()); 19 | // // 超出最大缓存 20 | // if (cause == RemovalCause.SIZE) { 21 | // 22 | // } 23 | // // 超出过期时间 24 | // if (cause == RemovalCause.EXPIRED) { 25 | // // do something 26 | // } 27 | // // 显式移除 28 | // if (cause == RemovalCause.EXPLICIT) { 29 | // // do something 30 | // } 31 | // // 旧数据被更新 32 | // if (cause == RemovalCause.REPLACED) { 33 | // // do something 34 | // } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | plasticene-boot-starter-parent 9 | com.plasticene.boot 10 | ${revision} 11 | ../pom.xml 12 | 13 | 14 | plasticene-boot-starter-mybatis 15 | 16 | 17 | 18 | com.plasticene.boot 19 | plasticene-common 20 | 21 | 22 | 23 | com.baomidou 24 | mybatis-plus-spring-boot3-starter 25 | 26 | 27 | 28 | com.baomidou 29 | mybatis-plus-jsqlparser 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | plasticene-boot-starter-parent 7 | com.plasticene.boot 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | plasticene-boot-starter-excel 13 | 14 | 15 | 16 | com.plasticene.boot 17 | plasticene-boot-starter-web 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | 23 | com.alibaba 24 | easyexcel 25 | 3.3.4 26 | 27 | 28 | 29 | 30 | 31 | 8 32 | 8 33 | 34 | 35 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/event/BaseFlowInstanceListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.event; 2 | 3 | import org.springframework.context.ApplicationListener; 4 | import org.springframework.lang.NonNull; 5 | 6 | import java.util.Objects; 7 | 8 | /** 9 | * 流程实例事件监听器抽象 10 | * 流程实例状态变更会发布事件,这时候监听实例事件的监听器都会收到事件通知 11 | * 不同的业务发起审批,生成流程实例,这样流程实例事件会通知到所有的业务监听器 12 | * 但是只需要该流程实例对应的业务监听器处理事件,其他业务的监听器不做任何处理 13 | * @author ZFJ 14 | * @date 2025/9/8 15 | */ 16 | public abstract class BaseFlowInstanceListener implements ApplicationListener { 17 | 18 | @Override 19 | public void onApplicationEvent(@NonNull InstanceEvent event) { 20 | String category = event.getCategory(); 21 | String businessType = businessType(); 22 | // 判断当前业务类型和实例事件的业务是否一致 23 | if (!Objects.equals(businessType, category)) { 24 | return; 25 | } 26 | // 真正处理实例事件 27 | doProcessInstanceEvent(event); 28 | } 29 | 30 | /** 31 | * 处理事件 32 | * @param event 事件 33 | */ 34 | public abstract void doProcessInstanceEvent(InstanceEvent event); 35 | 36 | /** 37 | * 监听器业务类型 要和流程模型类型一致 38 | * @return 业务类型 39 | */ 40 | public abstract String businessType(); 41 | } 42 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/anno/DistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.anno; 2 | 3 | import com.plasticene.boot.redis.core.enums.LockType; 4 | 5 | import java.lang.annotation.*; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/19 10:38 12 | */ 13 | 14 | @Target({ElementType.METHOD, ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface DistributedLock { 18 | 19 | /** 20 | * 分区名字,按照业务类型区分,比如用户服务→user,商品服务→product 21 | * 防止key重复导致不同业务功能获取同一把分布式锁 22 | */ 23 | String name() default ""; 24 | /** 25 | * 锁的key 26 | */ 27 | String key(); 28 | /** 29 | * 获取锁的最大尝试时间(单位 {@code unit}) 30 | * 该值大于0则使用 locker.tryLock 方法加锁,否则使用 locker.lock 方法 31 | */ 32 | long waitTime() default 0; 33 | /** 34 | * 加锁的时间(单位 {@code unit}),超过这个时间后锁便自动解锁; 35 | * 如果leaseTime为-1,则保持锁定直到显式解锁 36 | */ 37 | long leaseTime() default -1; 38 | /** 39 | * 参数的时间单位 40 | */ 41 | TimeUnit unit() default TimeUnit.SECONDS; 42 | 43 | 44 | /** 45 | * 锁类型,默认为可重入锁 46 | * @return 47 | */ 48 | LockType lockType() default LockType.REENTRANT; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/java/com/plasticene/boot/excel/core/ReadExcel.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.excel.core; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | import java.io.File; 6 | import java.util.List; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2024/4/22 15:55 12 | * 读取excel最订场接口封装 13 | */ 14 | public interface ReadExcel { 15 | 16 | /** =============>>>> 文件检查 */ 17 | 18 | void checkFile(MultipartFile file); 19 | 20 | void checkFileHead(MultipartFile file, List headList); 21 | 22 | void checkFileHead(MultipartFile file, List headList, Integer headRowNum); 23 | 24 | void checkFileDataIsEmpty(MultipartFile file); 25 | 26 | void checkFileDataIsEmpty(MultipartFile file, Integer headRowNum); 27 | 28 | void checkFileHeadAndDataIsEmpty(MultipartFile file, List headList); 29 | 30 | void checkFileHeadAndDataIsEmpty(MultipartFile file, List headList, Integer headRowNum); 31 | 32 | 33 | /** =============>>>> 上传文件 */ 34 | String uploadFile(MultipartFile file); 35 | 36 | /** =============>>>> 解析文件 */ 37 | void analysisFile(MultipartFile file); 38 | 39 | /** =============>>>> 完成收尾工作 */ 40 | void handleFinish(); 41 | 42 | 43 | 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/entity/FlowProcess.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.plasticene.boot.mybatis.core.metadata.BaseDO; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * 工作流-流程模型 13 | * @author ZFJ 14 | * @date 2025/9/2 15 | */ 16 | @EqualsAndHashCode(callSuper = true) 17 | @Data 18 | public class FlowProcess extends BaseDO { 19 | @TableId(type = IdType.AUTO) 20 | private Long id; 21 | /** 22 | * 公司id 23 | */ 24 | private Long orgId; 25 | /** 26 | * 流程唯一标识,字母区分大小写 27 | * 只能包含字母、数字、下划线、连字符和点号,且必须以字母开头 28 | */ 29 | private String code; 30 | /** 31 | * 流程名称 32 | */ 33 | private String name; 34 | /** 35 | * 流程分类 36 | */ 37 | private String category; 38 | /** 39 | * 流程状态 0:草稿 1:已发布 2:历史 40 | */ 41 | private Integer status; 42 | /** 43 | * 流程表单id 44 | */ 45 | private Long formId; 46 | /** 47 | * 流程模型配置 48 | */ 49 | private String model; 50 | /** 51 | * 流程说明 52 | */ 53 | private String remark; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.plasticene.boot 9 | plasticene-boot-starter-parent 10 | ${revision} 11 | ../pom.xml 12 | 13 | 14 | plasticene-boot-starter-license 15 | 16 | 17 | 18 | 19 | 20 | 21 | com.plasticene.boot 22 | plasticene-common 23 | 24 | 25 | 26 | com.plasticene.boot 27 | plasticene-boot-starter-web 28 | 29 | 30 | 31 | 32 | de.schlichtherle.truelicense 33 | truelicense-core 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /plasticene-boot-starter-cache/src/main/java/com/plasticene/boot/cache/core/prop/MultilevelCacheProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.cache.core.prop; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2022/7/20 16:27 10 | */ 11 | @ConfigurationProperties(prefix = "multilevel.cache") 12 | @Data 13 | public class MultilevelCacheProperties { 14 | 15 | /** 16 | * 一级本地缓存最大容量 17 | */ 18 | private Integer maxCapacity = 512; 19 | 20 | /** 21 | * 一级本地缓存初始化容量 22 | */ 23 | private Integer initCapacity = 64; 24 | 25 | /** 26 | * 缓存名称 27 | */ 28 | private String name = "multilevel-cache"; 29 | 30 | /** 31 | * 一级本地缓存名称 32 | */ 33 | private String caffeineName = "multilevel-caffeine-cache"; 34 | 35 | /** 36 | * 二级缓存名称 37 | */ 38 | private String redisName = "multilevel-redis-cache"; 39 | 40 | /** 41 | * 一级本地缓存过期时间 42 | */ 43 | private Integer caffeineExpireTime = 300; 44 | 45 | /** 46 | * 二级缓存过期时间 47 | */ 48 | private Integer redisExpireTime = 600; 49 | 50 | 51 | /** 52 | * 一级缓存开关 53 | */ 54 | private Boolean caffeineSwitch = true; 55 | 56 | 57 | 58 | 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/context/TenantContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.context; 2 | 3 | import com.alibaba.ttl.TransmittableThreadLocal; 4 | 5 | /** 6 | * @author fjzheng 7 | * @version 1.0 8 | * @date 2022/12/10 23:52 9 | */ 10 | public class TenantContextHolder { 11 | /** 12 | * 当前租户编号 13 | */ 14 | private static final ThreadLocal TENANT_ID = new TransmittableThreadLocal<>(); 15 | 16 | /** 17 | * 是否忽略租户 18 | */ 19 | private static final ThreadLocal IGNORE = new TransmittableThreadLocal<>(); 20 | 21 | /** 22 | * 获得租户编号。 23 | * 24 | * @return 租户编号 25 | */ 26 | public static Long getTenantId() { 27 | return TENANT_ID.get(); 28 | } 29 | 30 | 31 | public static void setTenantId(Long tenantId) { 32 | TENANT_ID.set(tenantId); 33 | } 34 | 35 | public static void setIgnore(Boolean ignore) { 36 | IGNORE.set(ignore); 37 | } 38 | 39 | /** 40 | * 当前是否忽略租户 41 | * 42 | * @return 是否忽略 43 | */ 44 | public static boolean isIgnore() { 45 | return Boolean.TRUE.equals(IGNORE.get()); 46 | } 47 | 48 | public static void clear() { 49 | TENANT_ID.remove(); 50 | IGNORE.remove(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/constant/OrderConstant.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.constant; 2 | 3 | /** 4 | * 5 | * 注意 注意 注意 6 | * 这里常量类型用于注解时,数据类型要和注解属性类型一直,不要发生包装类转换这些,不然编译报错。 7 | * @author fjzheng 8 | * @version 1.0 9 | * @date 2022/7/22 10:31 10 | */ 11 | public interface OrderConstant { 12 | 13 | int HIGHEST_PRECEDENCE = Integer.MIN_VALUE + 10000; 14 | /** 15 | * 接口访问日志打印切面 16 | */ 17 | int AOP_API_LOG = HIGHEST_PRECEDENCE; 18 | 19 | /** 20 | * 接口参数加解密切面 21 | */ 22 | int AOP_API_DECRYPT = HIGHEST_PRECEDENCE + 9; 23 | 24 | /** 25 | * 接口参数签名验证 26 | */ 27 | int AOP_API_SIGN_VERIFY = HIGHEST_PRECEDENCE + 10; 28 | 29 | /** 30 | * license验证切面 31 | */ 32 | int AOP_LICENSE = HIGHEST_PRECEDENCE + 100; 33 | 34 | /** 35 | * 接口限流切面 36 | */ 37 | int AOP_RATE_LIMIT = HIGHEST_PRECEDENCE + 200; 38 | 39 | /** 40 | * 分布式锁切面 41 | */ 42 | int AOP_LOCK = HIGHEST_PRECEDENCE + 300; 43 | 44 | /** 45 | * 日志trace过滤器 46 | */ 47 | int FILTER_TRACE = Integer.MIN_VALUE + 100; 48 | 49 | /** 50 | * license启动runner 51 | */ 52 | int RUNNER_LICENSE = HIGHEST_PRECEDENCE + 100; 53 | 54 | /** 55 | * 图案信息打印runner 56 | */ 57 | int RUNNER_BANNER = HIGHEST_PRECEDENCE + 1000; 58 | } 59 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/param/LicenseCreatorParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.param; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author fjzheng 13 | * @version 1.0 14 | * @date 2022/7/28 14:53 15 | */ 16 | @Data 17 | public class LicenseCreatorParam implements Serializable { 18 | /** 19 | * 证书生效时间 20 | */ 21 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 22 | private Date issuedTime=new Date(); 23 | 24 | /** 25 | * 证书失效时间 26 | */ 27 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 28 | private Date expiryTime; 29 | 30 | /** 31 | * 用户类型 32 | */ 33 | private String consumerType = "user"; 34 | 35 | /** 36 | * 用户数量 37 | */ 38 | private Integer consumerAmount = 1; 39 | 40 | /** 41 | * 描述信息 42 | */ 43 | private String description = "生成license"; 44 | 45 | 46 | /** 47 | * 业务相关的额外信息,在生成证书安装之后可以基于该信息做逻辑处理 48 | */ 49 | private Map extra = new HashMap<>(); 50 | 51 | /** 52 | * 服务器系统信息 53 | */ 54 | private SystemInfo systemInfo; 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /plasticene-boot-starter-oss/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | plasticene-boot-starter-parent 7 | com.plasticene.boot 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | plasticene-boot-starter-oss 13 | 14 | 15 | 16 | com.amazonaws 17 | aws-java-sdk-s3 18 | 1.12.423 19 | 20 | 21 | 22 | cn.hutool 23 | hutool-all 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter 29 | 30 | 31 | 32 | 33 | 34 | 8 35 | 8 36 | 37 | 38 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/java/com/plasticene/boot/excel/core/listener/DataExcelListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.excel.core.listener; 2 | 3 | import com.alibaba.excel.context.AnalysisContext; 4 | import com.alibaba.excel.event.AnalysisEventListener; 5 | import com.alibaba.excel.util.ListUtils; 6 | 7 | import java.util.List; 8 | import java.util.function.Consumer; 9 | 10 | /** 11 | * @author fjzheng 12 | * @version 1.0 13 | * @date 2024/4/22 19:01 14 | */ 15 | public class DataExcelListener extends AnalysisEventListener { 16 | /** 17 | * 缓存数量 18 | */ 19 | private static final int BATCH_COUNT = 1000; 20 | 21 | /** 22 | * 缓存的数据,不能一次性加载大批量数据到内存,容易OOM 23 | */ 24 | private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); 25 | 26 | 27 | /** 28 | * 数据处理器 29 | */ 30 | private final Consumer> dataHandler; 31 | 32 | public DataExcelListener(Consumer> dataHandler) { 33 | this.dataHandler = dataHandler; 34 | } 35 | 36 | @Override 37 | public void onException(Exception exception, AnalysisContext context) throws Exception { 38 | 39 | } 40 | 41 | @Override 42 | public void invoke(T data, AnalysisContext context) { 43 | 44 | } 45 | 46 | @Override 47 | public void doAfterAllAnalysed(AnalysisContext context) { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/LicenseCheckApplicationRunner.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core; 2 | 3 | import com.plasticene.boot.common.constant.OrderConstant; 4 | import com.plasticene.boot.license.core.processor.LicenseContentProcessor; 5 | import de.schlichtherle.license.LicenseContent; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.ApplicationArguments; 8 | import org.springframework.boot.ApplicationRunner; 9 | import org.springframework.core.annotation.Order; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2022/8/3 11:51 19 | */ 20 | @Order(OrderConstant.RUNNER_LICENSE) 21 | public class LicenseCheckApplicationRunner implements ApplicationRunner { 22 | @Autowired 23 | private LicenseVerify licenseVerify; 24 | @Autowired(required = false) 25 | private List processors = Collections.emptyList(); 26 | 27 | @Override 28 | public void run(ApplicationArguments args) { 29 | LicenseContent content = licenseVerify.install(); 30 | // 扩展点,在证书安装之后对licenseContent进行业务逻辑处理,比如数据加载,开关判断等等 31 | // 这里参考了spring的后置处理器,其实我们一般实现一个处理器逻辑处理就可以了,当然了也可以实现多个,所以这里是数组 32 | processors.forEach(processor -> processor.process(content)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/utils/IpUtil.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.utils; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.springframework.web.context.request.RequestContextHolder; 6 | import org.springframework.web.context.request.ServletRequestAttributes; 7 | 8 | 9 | /** 10 | * @author fjzheng 11 | * @version 1.0 12 | * @date 2024/5/14 15:09 13 | */ 14 | public class IpUtil { 15 | private static final String UNKNOWN = "unknown"; 16 | 17 | public static String getIpAddress() { 18 | HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 19 | String ip = request.getHeader("x-forwarded-for"); 20 | if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 21 | ip = request.getHeader("Proxy-Client-IP"); 22 | } 23 | if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 24 | ip = request.getHeader("WL-Proxy-Client-IP"); 25 | } 26 | if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 27 | ip = request.getRemoteAddr(); 28 | } 29 | 30 | // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 31 | if (StringUtils.isNotBlank(ip) && ip.indexOf(',') > 0) { 32 | ip = ip.substring(0, ip.indexOf(",")); 33 | } 34 | return ip; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/core/task/DelayTask.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.core.task; 2 | 3 | import lombok.Data; 4 | import lombok.NonNull; 5 | 6 | import java.util.concurrent.Delayed; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * 延时任务封装定义 11 | * @author ZFJ 12 | * @date 2025/10/16 13 | */ 14 | @Data 15 | public class DelayTask implements Delayed { 16 | 17 | /** 18 | * 队列名称,区分不同的业务类型 19 | */ 20 | private final String queueName; 21 | /** 22 | * 延时任务id,执行任务时通过id获取任务详情 23 | */ 24 | private final String taskId; 25 | /** 26 | * 任务执行时间 单位:ms 27 | */ 28 | private final long executeTime; 29 | 30 | 31 | public DelayTask(String queueName, String taskId, long executeTime) { 32 | this.queueName = queueName; 33 | this.taskId = taskId; 34 | this.executeTime = executeTime; 35 | } 36 | 37 | @Override 38 | public long getDelay(TimeUnit unit) { 39 | return unit.convert(executeTime - System.currentTimeMillis(), 40 | TimeUnit.MILLISECONDS); 41 | } 42 | 43 | @Override 44 | public int compareTo(@NonNull Delayed o) { 45 | return Long.compare(executeTime, ((DelayTask)o).executeTime); 46 | } 47 | 48 | /** 49 | * taskId可能重复,因为不同的业务队列,任务id可能是相同的 50 | * @return 唯一的业务任务id 51 | */ 52 | public String queueTaskId() { 53 | return this.queueName + ":" + this.taskId; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/param/FlowProcessParam.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.param; 2 | 3 | import com.plasticene.boot.flow.core.dto.ProcessNode; 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import jakarta.validation.constraints.NotBlank; 6 | import jakarta.validation.constraints.Pattern; 7 | import jakarta.validation.constraints.Size; 8 | import lombok.Data; 9 | 10 | /** 11 | * @author ZFJ 12 | * @date 2025/9/2 13 | */ 14 | @Data 15 | @Schema(description = "流程模型参数") 16 | public class FlowProcessParam { 17 | 18 | @Schema(description = "流程唯一标识, 区分大小写的") 19 | @NotBlank(message = "流程唯一标识不能为空") 20 | @Size(max = 16, message = "key长度不能超过16个字符") 21 | @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_\\-.]*$", 22 | message = "key只能包含字母、数字、下划线、连字符和点号,且必须以字母开头") 23 | private String code; 24 | @Schema(description = "流程名称") 25 | @NotBlank(message = "流程名称不能为空") 26 | @Size(max = 16, message = "名称长度不能超过16个字符") 27 | private String name; 28 | @Schema(description = "流程分类标识") 29 | @NotBlank(message = "流程分类不能为空") 30 | @Size(max = 16, message = "分类长度不能超过16个字符") 31 | private String category; 32 | @Schema(description = "流程描述") 33 | private String remark; 34 | 35 | @Schema(description = "表单id") 36 | private Long formId; 37 | @Schema(description = "流程模型节点配置") 38 | private ProcessNode processNode; 39 | @Schema(description = "流程id") 40 | private Long processId; 41 | } 42 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/validator/EnumValueValidator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.validator; 2 | 3 | import jakarta.validation.ConstraintValidator; 4 | import jakarta.validation.ConstraintValidatorContext; 5 | import org.springframework.util.CollectionUtils; 6 | 7 | import java.util.List; 8 | import java.util.Objects; 9 | 10 | /** 11 | * @author fjzheng 12 | * @version 1.0 13 | * @date 2025/5/23 14 | */ 15 | public class EnumValueValidator implements ConstraintValidator { 16 | 17 | private Class clz; 18 | 19 | @Override 20 | public void initialize(EnumValue constraintAnnotation) { 21 | clz = constraintAnnotation.linkEnum(); 22 | } 23 | 24 | @Override 25 | public boolean isValid(Object value, ConstraintValidatorContext context) { 26 | if (Objects.isNull(value)) { 27 | return true; 28 | } 29 | if (!clz.isEnum()) { 30 | return true; 31 | } 32 | CheckEnumValue[] enumConstants = clz.getEnumConstants(); 33 | if (enumConstants == null || enumConstants.length == 0) { 34 | return true; 35 | } 36 | CheckEnumValue enumConstant = enumConstants[0]; 37 | List enumValue = enumConstant.getEnumValue(); 38 | if (CollectionUtils.isEmpty(enumValue)) { 39 | return true; 40 | } 41 | return enumValue.contains(value); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /plasticene-common/src/main/java/com/plasticene/boot/common/aspect/AbstractAspectSupport.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.common.aspect; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.reflect.MethodSignature; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * @author fjzheng 10 | * @version 1.0 11 | * @date 2022/7/19 11:14 12 | */ 13 | public class AbstractAspectSupport { 14 | 15 | protected Method resolveMethod(ProceedingJoinPoint joinPoint) { 16 | MethodSignature signature = (MethodSignature)joinPoint.getSignature(); 17 | Class targetClass = joinPoint.getTarget().getClass(); 18 | 19 | Method method = getDeclaredMethodFor(targetClass, signature.getName(), 20 | signature.getMethod().getParameterTypes()); 21 | if (method == null) { 22 | throw new IllegalStateException("Cannot resolve target method: " + signature.getMethod().getName()); 23 | } 24 | return method; 25 | } 26 | 27 | private Method getDeclaredMethodFor(Class clazz, String name, Class... parameterTypes) { 28 | try { 29 | return clazz.getDeclaredMethod(name, parameterTypes); 30 | } catch (NoSuchMethodException e) { 31 | Class superClass = clazz.getSuperclass(); 32 | if (superClass != null) { 33 | return getDeclaredMethodFor(superClass, name, parameterTypes); 34 | } 35 | } 36 | return null; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /plasticene-boot-starter-delay-queue/src/main/java/com/plasticene/boot/delay/autoconfigure/DelayAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.delay.autoconfigure; 2 | 3 | import com.plasticene.boot.delay.core.DistributedDelayQueue; 4 | import com.plasticene.boot.delay.core.coordinator.Coordinator; 5 | import com.plasticene.boot.delay.core.coordinator.RedisCoordinator; 6 | import com.plasticene.boot.delay.core.prop.DelayProperties; 7 | import com.plasticene.boot.delay.core.storage.RedisTaskStorage; 8 | import com.plasticene.boot.delay.core.storage.TaskStorage; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | /** 15 | * @author ZFJ 16 | * @date 2025/10/17 17 | */ 18 | @Configuration 19 | @EnableConfigurationProperties({DelayProperties.class}) 20 | public class DelayAutoConfiguration { 21 | 22 | @ConditionalOnMissingBean(Coordinator.class) 23 | @Bean 24 | public Coordinator coordinator() { 25 | return new RedisCoordinator(); 26 | } 27 | 28 | @ConditionalOnMissingBean(TaskStorage.class) 29 | @Bean 30 | public TaskStorage taskStorage() { 31 | return new RedisTaskStorage(); 32 | } 33 | 34 | @Bean 35 | public DistributedDelayQueue distributedDelayQueue() { 36 | return new DistributedDelayQueue(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/aop/LicenseAspect.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.aop; 2 | 3 | import com.plasticene.boot.common.aspect.AbstractAspectSupport; 4 | import com.plasticene.boot.common.constant.OrderConstant; 5 | import com.plasticene.boot.common.exception.BizException; 6 | import com.plasticene.boot.license.core.LicenseVerify; 7 | import jakarta.annotation.Resource; 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.annotation.Around; 10 | import org.aspectj.lang.annotation.Aspect; 11 | import org.aspectj.lang.annotation.Pointcut; 12 | import org.springframework.core.annotation.Order; 13 | 14 | 15 | 16 | /** 17 | * 通过该切面实现License到期后服务不可用验证机制 18 | * 验证license有性能开销不能频繁,所以这里切面判断逻辑必须简单直接 19 | * @author fjzheng 20 | * @date 2022/8/3 21 | */ 22 | 23 | 24 | @Aspect 25 | @Order(OrderConstant.AOP_LICENSE) 26 | public class LicenseAspect extends AbstractAspectSupport { 27 | 28 | @Resource 29 | private LicenseVerify licenseVerify; 30 | 31 | // 指定切入点为License注解 32 | @Pointcut("@annotation(com.plasticene.boot.license.core.anno.License)") 33 | public void licenseAnnotationPointcut() { 34 | } 35 | 36 | // 环绕通知 37 | @Around("licenseAnnotationPointcut()") 38 | public Object aroundLicense(ProceedingJoinPoint pjp) throws Throwable { 39 | boolean valid = licenseVerify.isValid(); 40 | if (!valid) { 41 | throw new BizException("license is invalid"); 42 | } 43 | return pjp.proceed(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/entity/FlowInstance.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.plasticene.boot.mybatis.core.metadata.BaseDO; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/2 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | public class FlowInstance extends BaseDO { 18 | @TableId(type = IdType.AUTO) 19 | private Long id; 20 | /** 21 | * 公司id 22 | */ 23 | private Long orgId; 24 | /** 25 | * 申请人 26 | */ 27 | private Long userId; 28 | /** 29 | * 流程模型id 30 | */ 31 | private Long processId; 32 | /** 33 | * 状态 0:审批中 1:审批通过 2:审批拒绝 34 | */ 35 | private Integer status; 36 | /** 37 | * 开始时间 38 | */ 39 | private Date startTime; 40 | /** 41 | * 结束时间 42 | */ 43 | private Date endTime; 44 | /** 45 | * 当前节点key 46 | */ 47 | private String currentNodeKey; 48 | /** 49 | * 当前节点名称 50 | */ 51 | private String currentNodeName; 52 | /** 53 | * 业务id 54 | */ 55 | private Long businessId; 56 | 57 | /** 58 | * 模型快照 59 | */ 60 | private String model; 61 | 62 | /** 63 | * 表单配置 64 | */ 65 | private String form; 66 | 67 | /** 68 | * 参数变量值 69 | */ 70 | private String varMap; 71 | 72 | /** 73 | * 流程分类 74 | */ 75 | private String category; 76 | } 77 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/schedule/LicenseTask.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.schedule; 2 | 3 | import com.plasticene.boot.license.core.processor.LicenseExpiryProcessor; 4 | import com.plasticene.boot.license.core.LicenseVerify; 5 | import de.schlichtherle.license.LicenseContent; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | 10 | import java.util.Date; 11 | import java.util.Objects; 12 | 13 | /** 14 | * @author ZFJ 15 | * @date 2025/7/15 16 | */ 17 | 18 | @Slf4j 19 | public class LicenseTask { 20 | @Autowired 21 | private LicenseVerify licenseVerify; 22 | @Autowired(required = false) 23 | private LicenseExpiryProcessor licenseExpiryProcessor; 24 | 25 | /** 26 | * 校验license是否合法有效 27 | */ 28 | @Scheduled(cron = "${ptc.license.check-cron:0 30 0 * * ?}") 29 | public void checkLicenseValidity() { 30 | try { 31 | LicenseContent content = licenseVerify.verify(); 32 | Date expiryDate = content.getNotAfter(); 33 | // 业务方可以基于有效期进行提前提醒啥的 34 | if (Objects.nonNull(licenseExpiryProcessor)) { 35 | licenseExpiryProcessor.warn(expiryDate); 36 | } 37 | } catch (Exception e) { 38 | log.error("check license failed", e); 39 | } 40 | } 41 | 42 | /** 43 | * license热更新 44 | */ 45 | @Scheduled(cron = "${ptc.license.refresh-cron:0 0 0/1 * * ?}") 46 | public void refreshLicense () { 47 | licenseVerify.refresh(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/utils/MDCTraceUtils.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.utils; 2 | 3 | import cn.hutool.core.util.IdUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.alibaba.ttl.TransmittableThreadLocal; 6 | import org.slf4j.MDC; 7 | 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | /** 11 | * @author fjzheng 12 | * @version 1.0 13 | * @date 2022/7/14 09:57 14 | */ 15 | public class MDCTraceUtils { 16 | /** 17 | * 追踪id的名称 18 | */ 19 | public static final String KEY_TRACE_ID = "traceId"; 20 | 21 | /** 22 | * 日志链路追踪id信息头 23 | */ 24 | public static final String TRACE_ID_HEADER = "x-traceId-header"; 25 | /** 26 | * filter的优先级,值越低越优先 27 | */ 28 | public static final int FILTER_ORDER = -1; 29 | 30 | // private static final TransmittableThreadLocal ttl = new TransmittableThreadLocal<>(); 31 | 32 | /** 33 | * 创建traceId并赋值MDC 34 | */ 35 | public static void addTrace() { 36 | String traceId = createTraceId(); 37 | MDC.put(KEY_TRACE_ID, traceId); 38 | } 39 | 40 | /** 41 | * 赋值MDC 42 | */ 43 | public static void putTrace(String traceId) { 44 | MDC.put(KEY_TRACE_ID, traceId); 45 | } 46 | 47 | /** 48 | * 获取MDC中的traceId值 49 | */ 50 | public static String getTraceId() { 51 | return MDC.get(KEY_TRACE_ID); 52 | } 53 | 54 | /** 55 | * 清除MDC的值 56 | */ 57 | public static void removeTrace() { 58 | MDC.remove(KEY_TRACE_ID); 59 | } 60 | 61 | /** 62 | * 创建traceId 63 | */ 64 | public static String createTraceId() { 65 | return IdUtil.getSnowflake().nextIdStr(); 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/entity/FlowTask.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.plasticene.boot.mybatis.core.metadata.BaseDO; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/2 14 | */ 15 | @Data 16 | @EqualsAndHashCode(callSuper = true) 17 | public class FlowTask extends BaseDO { 18 | @TableId(type = IdType.AUTO) 19 | private Long id; 20 | /** 21 | * 公司id 22 | */ 23 | private Long orgId; 24 | /** 25 | * 流程实例id 26 | */ 27 | private Long instanceId; 28 | /** 29 | * 节点名称 30 | */ 31 | private String nodeName; 32 | /** 33 | * 节点key 34 | */ 35 | private String nodeKey; 36 | /** 37 | * 节点类型 38 | */ 39 | private Integer nodeType; 40 | /** 41 | * 处理人 42 | */ 43 | private Long assignee; 44 | /** 45 | * 审批类型 0:人工审批 1:自动通过 2:自动拒绝 46 | */ 47 | private Integer approveType; 48 | /** 49 | * 多人审批方式 0:会签 1:或签 2:顺序审批 50 | */ 51 | private Integer approveMode; 52 | /** 53 | * 状态 0:处理中 1:已完成 2:拒绝 54 | */ 55 | private Integer status; 56 | /** 57 | * 是否删除 0:否 1;是 58 | */ 59 | private Integer isDelete; 60 | /** 61 | * 开始时间 62 | */ 63 | private Date startTime; 64 | /** 65 | * 结束时间 66 | */ 67 | private Date endTime; 68 | /** 69 | * 审批意见 70 | */ 71 | private String comment; 72 | 73 | /** 74 | * 是否需要填写审批意见 0:否 1:是 75 | */ 76 | private Integer requireComment; 77 | } 78 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/autoconfigure/PlasticeneSwaggerAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.autoconfigure; 2 | 3 | import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; 4 | import com.plasticene.boot.web.core.prop.SwaggerProperties; 5 | import io.swagger.v3.oas.models.OpenAPI; 6 | import io.swagger.v3.oas.models.info.Contact; 7 | import io.swagger.v3.oas.models.info.Info; 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * @author fjzheng 15 | * @version 1.0 16 | * @date 2022/7/12 17:13 17 | */ 18 | @Configuration 19 | @EnableKnife4j 20 | @ConditionalOnProperty(prefix = "swagger-info", value = "enable", matchIfMissing = true) 21 | @EnableConfigurationProperties(SwaggerProperties.class) 22 | public class PlasticeneSwaggerAutoConfiguration { 23 | 24 | 25 | @Bean 26 | public OpenAPI customOpenAPI(SwaggerProperties properties) { 27 | return new OpenAPI().info(apiInfo(properties)); 28 | } 29 | 30 | /** 31 | * API 摘要信息 32 | */ 33 | private Info apiInfo(SwaggerProperties properties) { 34 | return new Info() 35 | .title(properties.getTitle()) 36 | .version(properties.getVersion()) 37 | .description(properties.getDescription()) 38 | .contact(new Contact() 39 | .name(properties.getAuthor()) 40 | .url(properties.getUrl()) 41 | .email(properties.getEmail())); 42 | 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/TenantDatabaseHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; 5 | import com.plasticene.boot.common.user.RequestUserHolder; 6 | import com.plasticene.boot.mybatis.core.context.TenantContextHolder; 7 | import com.plasticene.boot.mybatis.core.prop.TenantProperties; 8 | import net.sf.jsqlparser.expression.Expression; 9 | import net.sf.jsqlparser.expression.LongValue; 10 | 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2022/12/10 18:29 18 | */ 19 | public class TenantDatabaseHandler implements TenantLineHandler { 20 | private final Set ignoreTables = new HashSet<>(); 21 | 22 | public TenantDatabaseHandler(TenantProperties properties) { 23 | // 大小写的习惯不同,所以需要都添加进去 24 | properties.getIgnoreTables().forEach(table -> { 25 | ignoreTables.add(table.toLowerCase()); 26 | ignoreTables.add(table.toUpperCase()); 27 | }); 28 | } 29 | 30 | /** 31 | * 获取租户字段名 32 | *

33 | * 默认字段名叫: tenant_id 34 | * 35 | * @return 租户字段名 36 | */ 37 | @Override 38 | public String getTenantIdColumn() { 39 | return "org_id"; 40 | } 41 | 42 | 43 | @Override 44 | public Expression getTenantId() { 45 | return new LongValue(RequestUserHolder.getCurrentUser().getOrgId()); 46 | } 47 | 48 | @Override 49 | public boolean ignoreTable(String tableName) { 50 | return TenantContextHolder.isIgnore() 51 | || CollUtil.contains(ignoreTables, tableName); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/core/prop/LicenseProperties.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.core.prop; 2 | 3 | import com.plasticene.boot.license.core.enums.VerifySystemType; 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | /** 8 | * @author fjzheng 9 | * @version 1.0 10 | * @date 2022/7/28 17:55 11 | */ 12 | @ConfigurationProperties(prefix = "ptc.license") 13 | @Data 14 | public class LicenseProperties { 15 | /** 16 | * 证书subject 17 | */ 18 | private String subject = "license-demo"; 19 | 20 | /** 21 | * 公钥别称 22 | */ 23 | private String publicAlias = "publicCert"; 24 | 25 | /** 26 | * 访问公钥库的密码 27 | */ 28 | private String storePass = "plasticene666666"; 29 | 30 | /** 31 | * 证书生成路径 32 | */ 33 | private String licensePath = "/root/license/license.lic"; 34 | 35 | /** 36 | * 密钥库存储路径 37 | */ 38 | private String publicKeysStorePath = "/root/license/publicCerts.store"; 39 | 40 | 41 | /** 42 | * 密钥别称 43 | */ 44 | private String privateAlias = "privateKey"; 45 | 46 | /** 47 | * 密钥密码(需要妥善保管,不能让使用者知道) 48 | */ 49 | private String keyPass = "plasticene666666"; 50 | 51 | 52 | /** 53 | * 密钥库存储路径 54 | */ 55 | private String privateKeysStorePath = "/root/license/privateKeys.keystore"; 56 | 57 | /** 58 | * 是否开启license验证服务器系统信息, 不配置,默认开启 59 | */ 60 | private Boolean verifySystemSwitch = true; 61 | 62 | /** 63 | * 验证系统信息方式 {@link VerifySystemType} 64 | */ 65 | private VerifySystemType verifySystemType = VerifySystemType.CPU_ID; 66 | 67 | /** 68 | * 是否项目是验证license 69 | */ 70 | private Boolean enable = true; 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/LessThanOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | import com.plasticene.boot.flow.core.enums.FieldTypeEnum; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.Objects; 8 | 9 | /** 10 | * @author ZFJ 11 | * @date 2025/9/8 12 | */ 13 | @Slf4j 14 | public class LessThanOperator implements Operator { 15 | @Override 16 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 17 | try { 18 | if (fieldValue == null || inputValue == null) { 19 | return false; 20 | } 21 | if (Objects.equals(fieldType, FieldTypeEnum.NUMBER.getCode())) { 22 | // 数字类型统一转换成bigDecimal,防止小数精度丢失 23 | BigDecimal value = new BigDecimal(fieldValue.toString()); 24 | BigDecimal input = new BigDecimal(inputValue); 25 | return value.compareTo(input) < 0; 26 | } 27 | if (Objects.equals(fieldType, FieldTypeEnum.DATE.getCode())) { 28 | // 日期时间统一转换为时间戳, 好比较 29 | long timestamp = getTimestamp(fieldValue); 30 | return timestamp < Long.parseLong(inputValue); 31 | } 32 | } catch (Exception e) { 33 | log.error("【{}】operator error: fieldValue={}, inputValue={}", op(), fieldValue, inputValue, e); 34 | throw e; 35 | } 36 | return false; 37 | } 38 | 39 | @Override 40 | public void validate(Integer fieldType, String inputValue) { 41 | checkInputValue(fieldType, inputValue); 42 | checkNumberOperator(fieldType); 43 | } 44 | 45 | @Override 46 | public String op() { 47 | return "<"; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/GreaterThanOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | import com.plasticene.boot.flow.core.enums.FieldTypeEnum; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.Objects; 8 | 9 | /** 10 | * @author ZFJ 11 | * @date 2025/9/8 12 | */ 13 | @Slf4j 14 | public class GreaterThanOperator implements Operator { 15 | @Override 16 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 17 | try { 18 | if (fieldValue == null || inputValue == null) { 19 | return false; 20 | } 21 | if (Objects.equals(fieldType, FieldTypeEnum.NUMBER.getCode())) { 22 | // 数字类型统一转换成bigDecimal,防止小数精度丢失 23 | BigDecimal value = new BigDecimal(fieldValue.toString()); 24 | BigDecimal input = new BigDecimal(inputValue); 25 | return value.compareTo(input) > 0; 26 | } 27 | if (Objects.equals(fieldType, FieldTypeEnum.DATE.getCode())) { 28 | // 日期时间统一转换为时间戳, 好比较 29 | long timestamp = getTimestamp(fieldValue); 30 | return timestamp > Long.parseLong(inputValue); 31 | } 32 | } catch (Exception e) { 33 | log.error("【{}】operator error: fieldValue={}, inputValue={}", op(), fieldValue, inputValue, e); 34 | throw e; 35 | } 36 | return false; 37 | } 38 | 39 | @Override 40 | public void validate(Integer fieldType, String inputValue) { 41 | checkInputValue(fieldType, inputValue); 42 | checkNumberOperator(fieldType); 43 | } 44 | 45 | @Override 46 | public String op() { 47 | return ">"; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/main/java/com/plasticene/boot/example/mybatis/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.mybatis.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.plasticene.boot.common.pojo.PageParam; 7 | import com.plasticene.boot.common.pojo.PageResult; 8 | import com.plasticene.boot.example.mybatis.dao.UserDAO; 9 | import com.plasticene.boot.example.mybatis.entity.User; 10 | import jakarta.annotation.Resource; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2025/6/24 19 | */ 20 | @Service 21 | public class UserService extends ServiceImpl { 22 | @Resource 23 | private UserDAO userDAO; 24 | 25 | 26 | 27 | public User getUserById(Long id) { 28 | return userDAO.selectById(id); 29 | } 30 | 31 | public User getUser(Long id) { 32 | return userDAO.getById(id); 33 | } 34 | 35 | @Transactional(rollbackFor = Exception.class) 36 | public void insertUser(User user) { 37 | userDAO.insert(user); 38 | } 39 | 40 | public PageResult listUsers(Integer pageNo, Integer pageSize, String name) { 41 | LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); 42 | if (StringUtils.isNotBlank(name)) { 43 | queryWrapper.eq(User::getName, name); 44 | } 45 | PageParam param = new PageParam(pageNo, pageSize); 46 | return userDAO.selectPage(param, queryWrapper); 47 | } 48 | 49 | 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/utils/SignUtil.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.utils; 2 | 3 | import com.plasticene.boot.common.utils.JsonUtils; 4 | import com.plasticene.boot.web.core.model.RequestInfo; 5 | import lombok.experimental.UtilityClass; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.util.Objects; 9 | import java.util.SortedMap; 10 | import java.util.TreeMap; 11 | 12 | /** 13 | * @author fjzheng 14 | * @version 1.0 15 | * @date 2023/4/26 18:40 16 | */ 17 | @Slf4j 18 | @UtilityClass 19 | public class SignUtil { 20 | 21 | public SortedMap beanToMap(Object obj) { 22 | if (Objects.isNull(obj)) { 23 | return new TreeMap(); 24 | } 25 | String s = JsonUtils.toJsonString(obj); 26 | TreeMap treeMap = JsonUtils.parseObject(s, TreeMap.class); 27 | return treeMap; 28 | } 29 | 30 | public String getContent(SortedMap sortedMap, String nonce, String timestamp) { 31 | StringBuilder sb = new StringBuilder(); 32 | sortedMap.forEach((k, v) -> { 33 | sb.append(k + "=" + v + "&"); 34 | }); 35 | // 这里是反其道而行之,不按常理出牌,给破解加大一丢丢难度 36 | sb.append(nonce).append("=nonce").append(timestamp).append("=timestamp"); 37 | return sb.toString(); 38 | } 39 | 40 | public static void main(String[] args) { 41 | RequestInfo requestInfo = new RequestInfo(); 42 | requestInfo.setRequestParams("can shu"); 43 | requestInfo.setIp("127.0.0.1"); 44 | requestInfo.setHttpMethod("post"); 45 | requestInfo.setUrl("/test"); 46 | requestInfo.setClassMethod("com.shepherd.test()"); 47 | SortedMap sortedMap = beanToMap(requestInfo); 48 | sortedMap.forEach((k, v) -> { 49 | System.out.println(k + "----" + v); 50 | }); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/operator/EqualsOperator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.operator; 2 | 3 | import com.plasticene.boot.common.exception.BizException; 4 | import com.plasticene.boot.flow.core.enums.FieldTypeEnum; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.Date; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @author ZFJ 13 | * @date 2025/9/3 14 | */ 15 | @Slf4j 16 | public class EqualsOperator implements Operator { 17 | @Override 18 | public boolean compare(Integer fieldType, Object fieldValue, String inputValue) { 19 | try { 20 | if (fieldValue == null || inputValue == null) { 21 | return false; 22 | } 23 | if (Objects.equals(fieldType, FieldTypeEnum.NUMBER.getCode())) { 24 | // 数字类型统一转换成bigDecimal,防止小数精度丢失 25 | BigDecimal value = new BigDecimal(fieldValue.toString()); 26 | BigDecimal input = new BigDecimal(inputValue); 27 | return input.compareTo(value) == 0; 28 | } 29 | if (Objects.equals(fieldType, FieldTypeEnum.DATE.getCode())) { 30 | // 日期时间统一转换为时间戳, 好比较 31 | long timestamp = getTimestamp(fieldValue); 32 | return Objects.equals(timestamp, Long.valueOf(inputValue)); 33 | } 34 | return Objects.equals(fieldValue.toString(), inputValue); 35 | } catch (Exception e) { 36 | log.error("【{}】operator error: fieldValue={}, inputValue={}", op(), fieldValue, inputValue, e); 37 | throw e; 38 | } 39 | } 40 | 41 | @Override 42 | public void validate(Integer fieldType, String inputValue) { 43 | checkInputValue(fieldType, inputValue); 44 | checkNumberOperator(fieldType); 45 | } 46 | 47 | @Override 48 | public String op() { 49 | return "="; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/enums/FlowProcessNodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author ZFJ 7 | * @date 2025/9/2 8 | */ 9 | public class FlowProcessNodeEnum { 10 | 11 | @Getter 12 | public enum Type { 13 | END(-1, "结束节点"), 14 | START(0, "开始节点"), 15 | APPROVE(1, "审批节点"), 16 | COPY(2, "抄送节点"), 17 | CONDITION_NODE(3, "条件结点"), 18 | CONDITION_BRANCH(4, "条件分支") 19 | ; 20 | 21 | private final Integer code; 22 | private final String name; 23 | 24 | Type(Integer code, String name) { 25 | this.code = code; 26 | this.name = name; 27 | } 28 | } 29 | 30 | @Getter 31 | public enum ApproveType { 32 | MANUAL(0, "人工审批"), 33 | AUTO_PASS(1, "自动通过"), 34 | AUTO_REJECT(2, "自动拒绝") 35 | ; 36 | 37 | 38 | private final Integer code; 39 | private final String name; 40 | 41 | ApproveType(Integer code, String name) { 42 | this.code = code; 43 | this.name = name; 44 | } 45 | } 46 | 47 | @Getter 48 | public enum AssigneeType { 49 | USER(0, "指定人员") 50 | 51 | 52 | ; 53 | private final Integer code; 54 | private final String name; 55 | 56 | AssigneeType(Integer code, String name) { 57 | this.code = code; 58 | this.name = name; 59 | } 60 | } 61 | 62 | @Getter 63 | public enum ApproveMode { 64 | ALL(0, "会签"), 65 | ANY(1,"或签"), 66 | ORDER(2, "顺序审批") 67 | ; 68 | 69 | private final Integer code; 70 | private final String name; 71 | 72 | ApproveMode(Integer code, String name) { 73 | this.code = code; 74 | this.name = name; 75 | } 76 | } 77 | 78 | 79 | 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/filter/WebTraceFilter.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.filter; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.plasticene.boot.web.core.utils.MDCTraceUtils; 5 | import jakarta.servlet.FilterChain; 6 | import jakarta.servlet.ServletException; 7 | import jakarta.servlet.http.HttpServletRequest; 8 | import jakarta.servlet.http.HttpServletResponse; 9 | import org.springframework.lang.NonNull; 10 | import org.springframework.web.filter.OncePerRequestFilter; 11 | 12 | 13 | import java.io.IOException; 14 | import java.util.List; 15 | 16 | 17 | /** 18 | * @author fjzheng 19 | * @version 1.0 20 | * @date 2022/7/13 18:20 21 | */ 22 | // 23 | public class WebTraceFilter extends OncePerRequestFilter { 24 | 25 | private static final List EXCLUDE_PATHS = List.of( 26 | "/doc.html", 27 | "/swagger-ui.html", 28 | "/v3/api-docs", 29 | "/favicon.ico", 30 | "/webjars" 31 | ); 32 | 33 | 34 | @Override 35 | protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, 36 | @NonNull FilterChain filterChain) throws IOException, ServletException { 37 | String path = request.getRequestURI(); 38 | // 如果路径在排除列表中,直接跳过 39 | if (EXCLUDE_PATHS.stream().anyMatch(path::startsWith)) { 40 | filterChain.doFilter(request, response); 41 | return; 42 | } 43 | try { 44 | String traceId = request.getHeader(MDCTraceUtils.TRACE_ID_HEADER); 45 | if (StrUtil.isEmpty(traceId)) { 46 | MDCTraceUtils.addTrace(); 47 | } else { 48 | MDCTraceUtils.putTrace(traceId); 49 | } 50 | filterChain.doFilter(request, response); 51 | } finally { 52 | MDCTraceUtils.removeTrace(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/interceptor/FeignInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.interceptor; 2 | 3 | import com.plasticene.boot.web.core.utils.MDCTraceUtils; 4 | import feign.RequestInterceptor; 5 | import feign.RequestTemplate; 6 | import jakarta.servlet.http.HttpServletRequest; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.web.context.request.RequestContextHolder; 9 | import org.springframework.web.context.request.ServletRequestAttributes; 10 | 11 | import java.util.Enumeration; 12 | import java.util.Objects; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2022/7/26 17:09 18 | */ 19 | public class FeignInterceptor implements RequestInterceptor { 20 | @Override 21 | public void apply(RequestTemplate requestTemplate) { 22 | ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 23 | // 传递请求相关header 24 | if (requestAttributes != null) { 25 | HttpServletRequest request = requestAttributes.getRequest(); 26 | Enumeration headerNames = request.getHeaderNames(); 27 | if (headerNames != null) { 28 | while (headerNames.hasMoreElements()) { 29 | String name = headerNames.nextElement(); 30 | // 跳过 content-length 31 | if (Objects.equals("content-length", name)){ 32 | continue; 33 | } 34 | String value = request.getHeader(name); 35 | requestTemplate.header(name, value); 36 | } 37 | } 38 | } 39 | // 传递日志追踪的traceId 40 | String traceId = MDCTraceUtils.getTraceId(); 41 | if (StringUtils.isNotBlank(traceId)) { 42 | requestTemplate.header(MDCTraceUtils.TRACE_ID_HEADER, traceId); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plasticene-boot-starter-flow/src/main/java/com/plasticene/boot/flow/core/service/impl/FlowProcessServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.flow.core.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.plasticene.boot.common.utils.PtcBeanUtils; 6 | import com.plasticene.boot.flow.core.dao.FlowProcessDAO; 7 | import com.plasticene.boot.flow.core.entity.FlowProcess; 8 | import com.plasticene.boot.flow.core.param.FlowProcessParam; 9 | import com.plasticene.boot.flow.core.service.FlowProcessService; 10 | import jakarta.annotation.Resource; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | /** 15 | * @author ZFJ 16 | * @date 2025/9/2 17 | */ 18 | @Service 19 | public class FlowProcessServiceImpl extends ServiceImpl implements FlowProcessService { 20 | @Resource 21 | private FlowProcessDAO flowProcessDAO; 22 | 23 | @Transactional(rollbackFor = Exception.class) 24 | @Override 25 | public Long createFlowProcess(FlowProcessParam param) { 26 | FlowProcess flowProcess = PtcBeanUtils.copy(param, FlowProcess.class); 27 | flowProcess.setOrgId(0L); 28 | if (param.getProcessNode() != null) { 29 | flowProcess.setModel(JSON.toJSONString(param.getProcessNode())); 30 | } 31 | flowProcessDAO.insert(flowProcess); 32 | return flowProcess.getId(); 33 | } 34 | 35 | @Transactional(rollbackFor = Exception.class) 36 | @Override 37 | public void updateFlowProcess(FlowProcessParam param) { 38 | FlowProcess flowProcess = PtcBeanUtils.copy(param, FlowProcess.class); 39 | flowProcess.setId(param.getProcessId()); 40 | if (param.getProcessNode() != null) { 41 | flowProcess.setModel(JSON.toJSONString(param.getProcessNode())); 42 | } 43 | flowProcessDAO.updateById(flowProcess); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/EncryptTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.plasticene.boot.mybatis.core.encrypt.EncryptService; 5 | import jakarta.annotation.Resource; 6 | import org.apache.ibatis.type.BaseTypeHandler; 7 | import org.apache.ibatis.type.JdbcType; 8 | 9 | import java.sql.CallableStatement; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2022/7/22 14:37 18 | */ 19 | public class EncryptTypeHandler extends BaseTypeHandler { 20 | 21 | @Resource 22 | private EncryptService encryptService; 23 | 24 | @Override 25 | public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { 26 | ps.setString(i, encryptService.encrypt((String)parameter)); 27 | } 28 | @Override 29 | @SuppressWarnings("unchecked") 30 | public T getNullableResult(ResultSet rs, String columnName) throws SQLException { 31 | String columnValue = rs.getString(columnName); 32 | //有一些可能是空字符 33 | return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue); 34 | } 35 | 36 | @Override 37 | @SuppressWarnings("unchecked") 38 | public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 39 | String columnValue = rs.getString(columnIndex); 40 | return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue); 41 | } 42 | 43 | @Override 44 | @SuppressWarnings("unchecked") 45 | public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 46 | String columnValue = cs.getString(columnIndex); 47 | return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue); 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/SetTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import org.apache.ibatis.type.JdbcType; 6 | import org.apache.ibatis.type.TypeHandler; 7 | 8 | import java.sql.CallableStatement; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.Set; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2025/6/24 19 | */ 20 | public abstract class SetTypeHandler implements TypeHandler> { 21 | 22 | private static final String SEPARATOR = ","; 23 | 24 | @Override 25 | public void setParameter(PreparedStatement ps, int i, Set parameter, JdbcType jdbcType) throws SQLException { 26 | // 分隔符 27 | ps.setString(i, CollUtil.join(parameter, SEPARATOR)); 28 | } 29 | 30 | @Override 31 | public Set getResult(ResultSet rs, String columnName) throws SQLException { 32 | String value = rs.getString(columnName); 33 | return parseSet(value); 34 | } 35 | 36 | @Override 37 | public Set getResult(ResultSet rs, int columnIndex) throws SQLException { 38 | String value = rs.getString(columnIndex); 39 | return parseSet(value); 40 | } 41 | 42 | @Override 43 | public Set getResult(CallableStatement cs, int columnIndex) throws SQLException { 44 | String value = cs.getString(columnIndex); 45 | return parseSet(value); 46 | } 47 | 48 | private Set parseSet(String value) { 49 | if (StrUtil.isBlank(value)) { 50 | return null; 51 | } 52 | return StrUtil.split(value, SEPARATOR).stream() 53 | .map(this::parseItem) 54 | .collect(Collectors.toSet()); 55 | } 56 | 57 | // 子类需实现具体类型的转换逻辑 58 | protected abstract T parseItem(String value); 59 | } 60 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/handlers/type/ListTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.handlers.type; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import org.apache.ibatis.type.JdbcType; 6 | import org.apache.ibatis.type.TypeHandler; 7 | 8 | import java.sql.CallableStatement; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2025/6/24 19 | */ 20 | public abstract class ListTypeHandler implements TypeHandler> { 21 | 22 | private static final String SEPARATOR = ","; 23 | 24 | @Override 25 | public void setParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException { 26 | // 分隔符 27 | ps.setString(i, CollUtil.join(parameter, SEPARATOR)); 28 | } 29 | 30 | @Override 31 | public List getResult(ResultSet rs, String columnName) throws SQLException { 32 | String value = rs.getString(columnName); 33 | return parseList(value); 34 | } 35 | 36 | @Override 37 | public List getResult(ResultSet rs, int columnIndex) throws SQLException { 38 | String value = rs.getString(columnIndex); 39 | return parseList(value); 40 | } 41 | 42 | @Override 43 | public List getResult(CallableStatement cs, int columnIndex) throws SQLException { 44 | String value = cs.getString(columnIndex); 45 | return parseList(value); 46 | } 47 | 48 | private List parseList(String value) { 49 | if (StrUtil.isBlank(value)) { 50 | return null; 51 | } 52 | return StrUtil.split(value, SEPARATOR).stream() 53 | .map(this::parseItem) 54 | .collect(Collectors.toList()); 55 | } 56 | 57 | // 子类需实现具体类型的转换逻辑 58 | protected abstract T parseItem(String value); 59 | } 60 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-mybatis-example/src/main/java/com/plasticene/boot/example/mybatis/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.example.mybatis.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; 8 | import com.plasticene.boot.mybatis.core.handlers.EncryptTypeHandler; 9 | import com.plasticene.boot.mybatis.core.handlers.type.LongSetTypeHandler; 10 | import com.plasticene.boot.mybatis.core.handlers.type.StringListTypeHandler; 11 | import com.plasticene.boot.mybatis.core.metadata.BaseDO; 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | 15 | import java.util.*; 16 | 17 | /** 18 | * @author fjzheng 19 | * @version 1.0 20 | * @date 2025/6/24 21 | */ 22 | 23 | 24 | @EqualsAndHashCode(callSuper = true) 25 | @Data 26 | // 注意使用类型处理器时,必须设置autoResultMap = true,否则不生效 27 | @TableName(value = "tb_user", autoResultMap = true) 28 | public class User extends BaseDO { 29 | @TableId(type = IdType.AUTO) 30 | private Long id; 31 | private String userNo; 32 | private Integer gender; 33 | private Date birthday; 34 | private Integer isDelete; 35 | private String address; 36 | 37 | // --------- 多租户 38 | private Long orgId; 39 | 40 | // --------- 加密存储字段 41 | // @TableField(typeHandler = EncryptTypeHandler.class) 42 | private String name; 43 | // @TableField(typeHandler = EncryptTypeHandler.class) 44 | private String phone; 45 | // @TableField(typeHandler = EncryptTypeHandler.class) 46 | private String email; 47 | 48 | // -------- 复合字段类型处理 49 | @TableField(typeHandler = LongSetTypeHandler.class) 50 | private Set roleId; 51 | @TableField(typeHandler = StringListTypeHandler.class) 52 | private List hobby; 53 | @TableField(typeHandler = JacksonTypeHandler.class) 54 | private Map remark; 55 | } 56 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/autoconfigure/LicenseAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.autoconfigure; 2 | 3 | import com.plasticene.boot.license.core.LicenseCheckApplicationRunner; 4 | import com.plasticene.boot.license.core.LicenseCreator; 5 | import com.plasticene.boot.license.core.LicenseVerify; 6 | import com.plasticene.boot.license.core.aop.LicenseAspect; 7 | import com.plasticene.boot.license.core.prop.LicenseProperties; 8 | import com.plasticene.boot.license.core.schedule.LicenseTask; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 10 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.ComponentScan; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | /** 16 | * @author fjzheng 17 | * @version 1.0 18 | * @date 2022/7/29 10:07 19 | */ 20 | @Configuration 21 | @ComponentScan(basePackages = {"com.plasticene.boot.license"}) 22 | @EnableConfigurationProperties(LicenseProperties.class) 23 | public class LicenseAutoConfiguration { 24 | 25 | 26 | @Bean 27 | public LicenseCreator licenseCreator() { 28 | return new LicenseCreator(); 29 | } 30 | 31 | @Bean 32 | public LicenseVerify licenseVerify() { 33 | return new LicenseVerify(); 34 | } 35 | 36 | @Bean 37 | @ConditionalOnProperty(name = "ptc.license.enable", havingValue = "true", matchIfMissing = true) 38 | public LicenseTask licenseTask() { 39 | return new LicenseTask(); 40 | } 41 | 42 | @Bean 43 | @ConditionalOnProperty(name = "ptc.license.enable", havingValue = "true", matchIfMissing = true) 44 | public LicenseCheckApplicationRunner licenseCheckApplicationRunner() { 45 | return new LicenseCheckApplicationRunner(); 46 | } 47 | 48 | @Bean 49 | @ConditionalOnProperty(name = "ptc.license.enable", havingValue = "true", matchIfMissing = true) 50 | public LicenseAspect licenseAspect() { 51 | return new LicenseAspect(); 52 | } 53 | 54 | 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /plasticene-boot-starter-redis/src/main/java/com/plasticene/boot/redis/core/listener/AbstractChannelMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.redis.core.listener; 2 | 3 | import cn.hutool.core.util.TypeUtil; 4 | import com.plasticene.boot.common.utils.JsonUtils; 5 | import com.plasticene.boot.redis.core.message.AbstractChannelMessage; 6 | import lombok.SneakyThrows; 7 | import org.springframework.data.redis.connection.Message; 8 | import org.springframework.data.redis.connection.MessageListener; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | /** 13 | * @author fjzheng 14 | * @version 1.0 15 | * @date 2022/9/13 14:47 16 | */ 17 | public abstract class AbstractChannelMessageListener implements MessageListener { 18 | 19 | /** 20 | * 消息类型 21 | */ 22 | private final Class messageType; 23 | /** 24 | * Redis Channel 25 | */ 26 | private final String channel; 27 | 28 | 29 | @SneakyThrows 30 | protected AbstractChannelMessageListener() { 31 | this.messageType = getMessageClass(); 32 | this.channel = messageType.getDeclaredConstructor().newInstance().getChannel(); 33 | } 34 | 35 | /** 36 | * 获得 Sub 订阅的 Redis Channel 通道 37 | * 38 | * @return channel 39 | */ 40 | public final String getChannel() { 41 | return channel; 42 | } 43 | 44 | @Override 45 | public final void onMessage(Message message, byte[] bytes) { 46 | T messageObj = JsonUtils.parseObject(message.getBody(), messageType); 47 | this.onMessage(messageObj); 48 | } 49 | 50 | /** 51 | * 处理消息 52 | * 53 | * @param message 消息 54 | */ 55 | public abstract void onMessage(T message); 56 | 57 | /** 58 | * 通过解析类上的泛型,获得消息类型 59 | * 60 | * @return 消息类型 61 | */ 62 | @SuppressWarnings("unchecked") 63 | private Class getMessageClass() { 64 | Type type = TypeUtil.getTypeArgument(getClass(), 0); 65 | if (type == null) { 66 | throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); 67 | } 68 | return (Class) type; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-banner-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.plasticene.boot 7 | plasticene-boot-example 8 | ${revision} 9 | ../pom.xml 10 | 11 | plasticene-boot-banner-example 12 | 0.0.1-SNAPSHOT 13 | plasticene-boot-banner-example 14 | plasticene-boot-banner-example 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.plasticene.boot 31 | plasticene-boot-starter-banner 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.graalvm.buildtools 49 | native-maven-plugin 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-license-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.plasticene.boot 7 | plasticene-boot-example 8 | ${revision} 9 | ../pom.xml 10 | 11 | plasticene-boot-license-example 12 | 0.0.1-SNAPSHOT 13 | plasticene-boot-license-example 14 | plasticene-boot-license-example 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.plasticene.boot 31 | plasticene-boot-starter-banner 32 | 33 | 34 | com.plasticene.boot 35 | plasticene-boot-starter-license 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.graalvm.buildtools 49 | native-maven-plugin 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /plasticene-boot-starter-banner/src/main/java/com/plasticene/boot/banner/core/BannerApplicationRunner.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.banner.core; 2 | 3 | import cn.hutool.core.thread.ThreadUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.plasticene.boot.common.constant.OrderConstant; 6 | import jakarta.annotation.Resource; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.boot.ApplicationArguments; 10 | import org.springframework.boot.ApplicationRunner; 11 | import org.springframework.boot.autoconfigure.web.ServerProperties; 12 | import org.springframework.core.annotation.Order; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * @author fjzheng 18 | * @version 1.0 19 | * @date 2022/7/12 15:11 20 | */ 21 | @Slf4j 22 | @Order(OrderConstant.RUNNER_BANNER) 23 | public class BannerApplicationRunner implements ApplicationRunner { 24 | 25 | @Resource 26 | private ServerProperties serverProperties; 27 | 28 | @Value("${spring.application.name}") 29 | private String name; 30 | 31 | private static final String URL_PREFIX = "http://127.0.0.1:"; 32 | private static final String SWAGGER_SUFFIX = "/doc.html"; 33 | 34 | @Override 35 | public void run(ApplicationArguments args) { 36 | StringBuilder builder = new StringBuilder(URL_PREFIX + serverProperties.getPort()); 37 | String contextPath = serverProperties.getServlet().getContextPath(); 38 | if (StrUtil.isNotBlank(contextPath)) { 39 | if (! contextPath.startsWith("/")) { 40 | builder.append("/"); 41 | } 42 | builder.append(contextPath); 43 | } 44 | builder.append(SWAGGER_SUFFIX); 45 | ThreadUtil.execute(() -> { 46 | // 延迟 1 秒,尽量保证输出到结尾 47 | ThreadUtil.sleep(1, TimeUnit.SECONDS); 48 | String template = """ 49 | \n---------------------------------------------------------- 50 | (♥◠‿◠)ノ゙ {}启动成功啦 ლ(´ڡ`ლ) 51 | 接口文档: {} 52 | """; 53 | log.info(template, name, builder); 54 | }); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /plasticene-boot-starter-excel/src/main/java/com/plasticene/boot/excel/utils/ExcelUtil.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.excel.utils; 2 | 3 | import com.alibaba.excel.EasyExcel; 4 | import com.alibaba.excel.converters.longconverter.LongStringConverter; 5 | import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; 6 | import org.springframework.web.multipart.MultipartFile; 7 | 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.net.URLEncoder; 11 | import java.nio.charset.StandardCharsets; 12 | import java.util.List; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2024/5/8 14:57 18 | */ 19 | public class ExcelUtil { 20 | /** 21 | * 将列表以 Excel 响应给前端 22 | * 23 | * @param response 响应 24 | * @param filename 文件名 25 | * @param sheetName Excel sheet 名 26 | * @param head Excel head 头 27 | * @param data 数据列表哦 28 | * @param 泛型,保证 head 和 data 类型的一致性 29 | * @throws IOException 写入失败的情况 30 | */ 31 | public static void write(HttpServletResponse response, String filename, String sheetName, 32 | Class head, List data) throws IOException { 33 | // 输出 Excel 34 | EasyExcel.write(response.getOutputStream(), head) 35 | .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 36 | .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 37 | .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 38 | .sheet(sheetName).doWrite(data); 39 | // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 40 | response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); 41 | response.setContentType("application/vnd.ms-excel;charset=UTF-8"); 42 | } 43 | 44 | public static List read(MultipartFile file, Class head) throws IOException { 45 | return EasyExcel.read(file.getInputStream(), head, null) 46 | .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 47 | .doReadAllSync(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-flow-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.plasticene.boot 7 | plasticene-boot-example 8 | ${revision} 9 | ../pom.xml 10 | 11 | plasticene-boot-flow-example 12 | 0.0.1-SNAPSHOT 13 | plasticene-boot-flow-example 14 | plasticene-boot-flow-example 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.plasticene.boot 31 | plasticene-boot-starter-banner 32 | 33 | 34 | com.plasticene.boot 35 | plasticene-boot-starter-flow 36 | 37 | 38 | 39 | 40 | mysql 41 | mysql-connector-java 42 | 8.0.33 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /plasticene-boot-example/plasticene-boot-delay-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.plasticene.boot 7 | plasticene-boot-example 8 | ${revision} 9 | ../pom.xml 10 | 11 | 12 | plasticene-boot-delay-example 13 | 0.0.1-SNAPSHOT 14 | plasticene-boot-delay-example 15 | plasticene-boot-delay-example 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 21 31 | 32 | 33 | 34 | com.plasticene.boot 35 | plasticene-boot-starter-web 36 | 37 | 38 | com.plasticene.boot 39 | plasticene-boot-starter-banner 40 | 41 | 42 | 43 | com.plasticene.boot 44 | plasticene-boot-starter-delay-queue 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/global/RequestBodyWrapper.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.global; 2 | 3 | import jakarta.servlet.ReadListener; 4 | import jakarta.servlet.ServletInputStream; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.servlet.http.HttpServletRequestWrapper; 7 | import org.springframework.util.StreamUtils; 8 | 9 | 10 | import java.io.BufferedReader; 11 | import java.io.ByteArrayInputStream; 12 | import java.io.IOException; 13 | import java.io.InputStreamReader; 14 | import java.nio.charset.StandardCharsets; 15 | 16 | /** 17 | * @author fjzheng 18 | * @version 1.0 19 | * @date 2023/4/27 14:01 20 | */ 21 | public class RequestBodyWrapper extends HttpServletRequestWrapper { 22 | 23 | //用于将流保存下来 24 | private String body; 25 | 26 | public RequestBodyWrapper(HttpServletRequest request) throws IOException { 27 | super(request); 28 | body = new String(StreamUtils.copyToByteArray(request.getInputStream()), StandardCharsets.UTF_8); 29 | } 30 | 31 | /** 32 | * 重写getInputStream, 从body中获取请求参数 33 | * @return 34 | * @throws IOException 35 | */ 36 | @Override 37 | public ServletInputStream getInputStream() throws IOException { 38 | final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8")); 39 | return 40 | new ServletInputStream() { 41 | @Override 42 | public boolean isFinished() { 43 | return false; 44 | } 45 | 46 | @Override 47 | public boolean isReady() { 48 | return false; 49 | } 50 | 51 | @Override 52 | public void setReadListener(ReadListener readListener) { 53 | 54 | } 55 | 56 | @Override 57 | public int read() throws IOException { 58 | return byteArrayInputStream.read(); 59 | } 60 | }; 61 | } 62 | 63 | @Override 64 | public BufferedReader getReader() throws IOException { 65 | return new BufferedReader(new InputStreamReader(getInputStream())); 66 | } 67 | 68 | public String getBody() { 69 | return this.body; 70 | } 71 | 72 | public void setBody(String body) { 73 | this.body = body; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /plasticene-boot-starter-license/src/main/java/com/plasticene/boot/license/web/LicenseController.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.license.web; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.core.io.IoUtil; 5 | import com.plasticene.boot.common.exception.BizException; 6 | import com.plasticene.boot.license.core.LicenseCreator; 7 | import com.plasticene.boot.license.core.LicenseVerify; 8 | import com.plasticene.boot.license.core.param.LicenseCreatorParam; 9 | import io.swagger.v3.oas.annotations.Operation; 10 | import io.swagger.v3.oas.annotations.tags.Tag; 11 | import jakarta.annotation.Resource; 12 | import jakarta.servlet.http.HttpServletResponse; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.apache.commons.io.FileUtils; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | 18 | import java.io.BufferedInputStream; 19 | import java.io.File; 20 | import java.io.IOException; 21 | 22 | /** 23 | * @author fjzheng 24 | * @version 1.0 25 | * @date 2022/7/28 19:03 26 | */ 27 | @RestController 28 | @Tag(name = "license管理") 29 | @RequestMapping("/license") 30 | @Slf4j 31 | public class LicenseController { 32 | 33 | @Resource 34 | private LicenseCreator licenseCreator; 35 | @Resource 36 | private LicenseVerify licenseVerify; 37 | 38 | @PostMapping("/create") 39 | @Operation(summary = "生成license") 40 | public void create(@RequestBody LicenseCreatorParam creatorParam, HttpServletResponse response) throws IOException { 41 | File tempFile = new File("license_" + System.currentTimeMillis() + ".lic"); 42 | try { 43 | licenseCreator.generateLicense(creatorParam, tempFile); 44 | response.setContentType("application/octet-stream"); 45 | response.setHeader("Content-Disposition", "attachment;filename=license.lic"); 46 | BufferedInputStream inputStream = FileUtil.getInputStream(tempFile); 47 | IoUtil.copy(inputStream, response.getOutputStream()); 48 | } catch (Exception e) { 49 | log.error("生成license文件失败:", e); 50 | throw new BizException("生产license文件失败"); 51 | } finally { 52 | FileUtils.delete(tempFile); 53 | } 54 | } 55 | 56 | @PostMapping("/refresh") 57 | @Operation(summary = "热更新license") 58 | public void refreshLicense() { 59 | licenseVerify.refresh(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /plasticene-boot-starter-mybatis/src/main/java/com/plasticene/boot/mybatis/core/utils/MybatisUtils.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.mybatis.core.utils; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.plasticene.boot.common.pojo.PageParam; 7 | import net.sf.jsqlparser.expression.Alias; 8 | import net.sf.jsqlparser.schema.Column; 9 | import net.sf.jsqlparser.schema.Table; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author fjzheng 16 | * @version 1.0 17 | * @date 2022/7/12 13:36 18 | */ 19 | public class MybatisUtils { 20 | private static final String MYSQL_ESCAPE_CHARACTER = "`"; 21 | 22 | 23 | 24 | public static Page buildPage(PageParam pageParam) { 25 | // 页码 + 数量 26 | return new Page<>(pageParam.getPageNo(), pageParam.getPageSize()); 27 | } 28 | 29 | /** 30 | * 将拦截器添加到链中 31 | * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 32 | * 33 | * @param interceptor 链 34 | * @param inner 拦截器 35 | * @param index 位置 36 | */ 37 | public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) { 38 | List inners = new ArrayList<>(interceptor.getInterceptors()); 39 | inners.add(index, inner); 40 | interceptor.setInterceptors(inners); 41 | } 42 | 43 | /** 44 | * 获得 Table 对应的表名 45 | * 兼容 MySQL 转义表名 `t_xxx` 46 | * 47 | * @param table 表 48 | * @return 去除转移字符后的表名 49 | */ 50 | public static String getTableName(Table table) { 51 | String tableName = table.getName(); 52 | if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) { 53 | tableName = tableName.substring(1, tableName.length() - 1); 54 | } 55 | return tableName; 56 | } 57 | 58 | /** 59 | * 构建 Column 对象 60 | * 61 | * @param tableName 表名 62 | * @param tableAlias 别名 63 | * @param column 字段名 64 | * @return Column 对象 65 | */ 66 | public static Column buildColumn(String tableName, Alias tableAlias, String column) { 67 | return new Column(tableAlias != null ? tableAlias.getName() + "." + column : column); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /plasticene-boot-starter-web/src/main/java/com/plasticene/boot/web/core/validator/CombineNotNullValidator.java: -------------------------------------------------------------------------------- 1 | package com.plasticene.boot.web.core.validator; 2 | 3 | import com.plasticene.boot.web.core.constant.ValidatorConstant; 4 | import jakarta.validation.ConstraintValidator; 5 | import jakarta.validation.ConstraintValidatorContext; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.expression.Expression; 8 | import org.springframework.expression.ExpressionParser; 9 | import org.springframework.expression.spel.standard.SpelExpressionParser; 10 | import org.springframework.web.context.request.RequestAttributes; 11 | import org.springframework.web.context.request.RequestContextHolder; 12 | 13 | import java.util.Objects; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | 16 | /** 17 | * @author fjzheng 18 | * @version 1.0 19 | * @date 2025/5/23 20 | */ 21 | public class CombineNotNullValidator implements ConstraintValidator { 22 | 23 | // 解析SpEL有一定开销, 缓存表达式 24 | private static final ConcurrentHashMap EXPRESSION_CACHE = new ConcurrentHashMap<>(); 25 | // SpelExpressionParser是线程安全的 26 | private static final ExpressionParser parser = new SpelExpressionParser(); 27 | // 条件表达式字符串 28 | private String condition; 29 | 30 | 31 | @Override 32 | public void initialize(CombineNotNull constraintAnnotation) { 33 | condition = constraintAnnotation.condition(); 34 | } 35 | 36 | @Override 37 | public boolean isValid(Object value, ConstraintValidatorContext context) { 38 | // 表达式为空 39 | if (StringUtils.isBlank(condition)) { 40 | return true; 41 | } 42 | // 获取根对象(被校验的对象) 43 | RequestAttributes requestAttributes = Objects.requireNonNull(RequestContextHolder.getRequestAttributes()); 44 | Object requestBody = requestAttributes.getAttribute(ValidatorConstant.VALID_REQUEST_BODY, RequestAttributes.SCOPE_REQUEST); 45 | if (requestBody == null) { 46 | return true; 47 | } 48 | Expression expression = EXPRESSION_CACHE.computeIfAbsent( 49 | condition, 50 | parser::parseExpression 51 | ); 52 | Boolean result = expression.getValue(requestBody, Boolean.class); 53 | if (Boolean.FALSE.equals(result)) { 54 | return true; 55 | } 56 | return value != null; 57 | } 58 | } 59 | --------------------------------------------------------------------------------