diff --git a/README.md b/README.md deleted file mode 100644 index 01ed42e1f4537bc8b87301c30169a7144d36657b..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# xfg-frame-archetype - DDD 脚手架 - -## 重要信息 - -- 2核4G 可部署整套环境开发学习 [京东云服务器 2核4G 132元/1年或者3年的](https://3.cn/1K-cfT7D) -- 工程中没有提供 application/case 层,如果你的工程较大,可以使用脚手架构建完工程后,自己新增加此模块 -- 框架使用文档:[https://bugstack.cn/md/road-map/ddd-archetype.html](https://bugstack.cn/md/road-map/ddd-archetype.html) - 此文章下还有系列的 DDD 知识 - -## Maven - 阿里云镜像 - -```java - - - - - alimaven - central - aliyun maven - https://maven.aliyun.com/nexus/content/repositories/central/ - - - -``` - -- 没有镜像你可能会出现拉取很慢的问题,以及错误。 diff --git a/pom.xml b/pom.xml index e595274ee56d42876c00fd71243b233aba24b5d6..2a711a7a8479bc1893672365444c6e5b2d48786d 100644 --- a/pom.xml +++ b/pom.xml @@ -24,15 +24,6 @@ UTF-8 - - - xiaofuge - 184172133@qq.com - fuzhengwei - https://github.com/fuzhengwei - - - Apache License, Version 2.0 @@ -48,6 +39,13 @@ + + org.redisson + redisson-spring-boot-starter + 3.23.4 + + + org.mybatis.spring.boot mybatis-spring-boot-starter @@ -123,6 +121,7 @@ xfg-frame-archetype-lite-trigger 1.0-SNAPSHOT + diff --git a/xfg-frame-archetype-lite-app/data/log/log-info-2025-03-02.0.log b/xfg-frame-archetype-lite-app/data/log/log-info-2025-03-02.0.log new file mode 100644 index 0000000000000000000000000000000000000000..d696e87d0e80b83b11f80316a1b52b57278d82b5 --- /dev/null +++ b/xfg-frame-archetype-lite-app/data/log/log-info-2025-03-02.0.log @@ -0,0 +1,8 @@ +25-03-02.22:16:34.489 [main ] INFO AwardDaoTest - Starting AwardDaoTest using Java 17.0.10 on xruicc with PID 4280 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-02.22:16:34.490 [main ] INFO AwardDaoTest - The following 1 profile is active: "dev" +25-03-02.22:16:36.666 [main ] INFO AwardDaoTest - Started AwardDaoTest in 2.655 seconds (JVM running for 3.732) +25-03-02.22:16:37.163 [main ] INFO HikariDataSource - HikariPool-1 - Starting... +25-03-02.22:16:37.722 [main ] INFO HikariDataSource - HikariPool-1 - Start completed. +25-03-02.22:16:38.021 [main ] INFO AwardDaoTest - 测试结果:[{"awardConfig":"1,100","awardDesc":"用户积分【优先透彻规则范围,如果没有则走配置】","awardId":101,"awardKey":"user_credit_random"},{"awardConfig":"5","awardDesc":"OpenAI 增加使用次数","awardId":102,"awardKey":"openai_use_count"},{"awardConfig":"10","awardDesc":"OpenAI 增加使用次数","awardId":103,"awardKey":"openai_use_count"},{"awardConfig":"20","awardDesc":"OpenAI 增加使用次数","awardId":104,"awardKey":"openai_use_count"},{"awardConfig":"gpt-4","awardDesc":"OpenAI 增加模型","awardId":105,"awardKey":"openai_model"},{"awardConfig":"dall-e-2","awardDesc":"OpenAI 增加模型","awardId":106,"awardKey":"openai_model"},{"awardConfig":"dall-e-3","awardDesc":"OpenAI 增加模型","awardId":107,"awardKey":"openai_model"},{"awardConfig":"100","awardDesc":"OpenAI 增加使用次数","awardId":108,"awardKey":"openai_use_count"},{"awardConfig":"gpt-4,dall-e-2,dall-e-3","awardDesc":"OpenAI 增加模型","awardId":109,"awardKey":"openai_model"}] +25-03-02.22:16:38.034 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown initiated... +25-03-02.22:16:38.046 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown completed. diff --git a/xfg-frame-archetype-lite-app/data/log/log_info.log b/xfg-frame-archetype-lite-app/data/log/log_info.log index d696e87d0e80b83b11f80316a1b52b57278d82b5..94c556faaf20f9debdd07122ddb647224c307d6e 100644 --- a/xfg-frame-archetype-lite-app/data/log/log_info.log +++ b/xfg-frame-archetype-lite-app/data/log/log_info.log @@ -1,8 +1,92 @@ -25-03-02.22:16:34.489 [main ] INFO AwardDaoTest - Starting AwardDaoTest using Java 17.0.10 on xruicc with PID 4280 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) -25-03-02.22:16:34.490 [main ] INFO AwardDaoTest - The following 1 profile is active: "dev" -25-03-02.22:16:36.666 [main ] INFO AwardDaoTest - Started AwardDaoTest in 2.655 seconds (JVM running for 3.732) -25-03-02.22:16:37.163 [main ] INFO HikariDataSource - HikariPool-1 - Starting... -25-03-02.22:16:37.722 [main ] INFO HikariDataSource - HikariPool-1 - Start completed. -25-03-02.22:16:38.021 [main ] INFO AwardDaoTest - 测试结果:[{"awardConfig":"1,100","awardDesc":"用户积分【优先透彻规则范围,如果没有则走配置】","awardId":101,"awardKey":"user_credit_random"},{"awardConfig":"5","awardDesc":"OpenAI 增加使用次数","awardId":102,"awardKey":"openai_use_count"},{"awardConfig":"10","awardDesc":"OpenAI 增加使用次数","awardId":103,"awardKey":"openai_use_count"},{"awardConfig":"20","awardDesc":"OpenAI 增加使用次数","awardId":104,"awardKey":"openai_use_count"},{"awardConfig":"gpt-4","awardDesc":"OpenAI 增加模型","awardId":105,"awardKey":"openai_model"},{"awardConfig":"dall-e-2","awardDesc":"OpenAI 增加模型","awardId":106,"awardKey":"openai_model"},{"awardConfig":"dall-e-3","awardDesc":"OpenAI 增加模型","awardId":107,"awardKey":"openai_model"},{"awardConfig":"100","awardDesc":"OpenAI 增加使用次数","awardId":108,"awardKey":"openai_use_count"},{"awardConfig":"gpt-4,dall-e-2,dall-e-3","awardDesc":"OpenAI 增加模型","awardId":109,"awardKey":"openai_model"}] -25-03-02.22:16:38.034 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown initiated... -25-03-02.22:16:38.046 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown completed. +25-03-03.21:06:31.068 [main ] INFO ApiTest - Starting ApiTest using Java 17.0.10 on xruicc with PID 27140 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.21:06:31.069 [main ] INFO ApiTest - The following 1 profile is active: "dev" +25-03-03.21:06:32.143 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.21:06:32.148 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.21:06:32.189 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 14 ms. Found 0 Redis repository interfaces. +25-03-03.21:06:33.173 [main ] INFO Version - Redisson 3.23.4 +25-03-03.21:06:33.646 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.21:06:33.662 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.21:06:35.292 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.21:06:35.347 [main ] INFO ApiTest - Started ApiTest in 4.759 seconds (JVM running for 5.923) +25-03-03.21:06:35.870 [main ] INFO ApiTest - 测试结果:100 +25-03-03.22:38:56.367 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 19328 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.22:38:56.368 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.22:38:57.244 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.22:38:57.246 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.22:38:57.278 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 16 ms. Found 0 Redis repository interfaces. +25-03-03.22:38:58.526 [main ] INFO Version - Redisson 3.23.4 +25-03-03.22:38:59.017 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:38:59.039 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:39:00.415 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.22:39:00.472 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.546 seconds (JVM running for 5.706) +25-03-03.22:39:01.015 [main ] INFO HikariDataSource - HikariPool-1 - Starting... +25-03-03.22:39:01.417 [main ] INFO HikariDataSource - HikariPool-1 - Start completed. +25-03-03.22:39:15.717 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown initiated... +25-03-03.22:39:15.734 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown completed. +25-03-03.22:49:25.462 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 22388 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.22:49:25.462 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.22:49:26.394 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.22:49:26.396 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.22:49:26.428 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 17 ms. Found 0 Redis repository interfaces. +25-03-03.22:49:27.663 [main ] INFO Version - Redisson 3.23.4 +25-03-03.22:49:28.164 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:49:28.182 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:49:29.535 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.22:49:29.582 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.547 seconds (JVM running for 5.653) +25-03-03.22:50:59.298 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 27376 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.22:50:59.299 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.22:51:00.158 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.22:51:00.160 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.22:51:00.191 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 17 ms. Found 0 Redis repository interfaces. +25-03-03.22:51:01.355 [main ] INFO Version - Redisson 3.23.4 +25-03-03.22:51:01.816 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:51:01.837 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:51:03.156 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.22:51:03.209 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.371 seconds (JVM running for 5.499) +25-03-03.22:51:03.710 [main ] INFO HikariDataSource - HikariPool-1 - Starting... +25-03-03.22:51:04.076 [main ] INFO HikariDataSource - HikariPool-1 - Start completed. +25-03-03.22:51:04.349 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown initiated... +25-03-03.22:51:04.363 [SpringApplicationShutdownHook] INFO HikariDataSource - HikariPool-1 - Shutdown completed. +25-03-03.22:55:30.466 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 11100 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.22:55:30.467 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.22:55:31.327 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.22:55:31.332 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.22:55:31.361 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 15 ms. Found 0 Redis repository interfaces. +25-03-03.22:55:32.533 [main ] INFO Version - Redisson 3.23.4 +25-03-03.22:55:32.979 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:55:32.996 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.22:55:34.444 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.22:55:34.503 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.551 seconds (JVM running for 5.69) +25-03-03.23:05:02.637 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 27872 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.23:05:02.638 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.23:05:03.612 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.23:05:03.615 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.23:05:03.646 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 17 ms. Found 0 Redis repository interfaces. +25-03-03.23:05:05.145 [main ] INFO Version - Redisson 3.23.4 +25-03-03.23:05:05.733 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:05:05.755 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:05:07.553 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.23:05:07.621 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 5.522 seconds (JVM running for 7.136) +25-03-03.23:14:35.673 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 23408 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.23:14:35.674 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.23:14:36.513 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.23:14:36.517 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.23:14:36.545 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 16 ms. Found 0 Redis repository interfaces. +25-03-03.23:14:37.757 [main ] INFO Version - Redisson 3.23.4 +25-03-03.23:14:38.190 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:14:38.206 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:14:39.491 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.23:14:39.534 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.288 seconds (JVM running for 5.373) +25-03-03.23:16:07.203 [main ] INFO StrategyArmoryTest - Starting StrategyArmoryTest using Java 17.0.10 on xruicc with PID 26864 (started by 15505 in D:\MarketingIntegrationSystem\xfg-frame-archetype-lite-app) +25-03-03.23:16:07.204 [main ] INFO StrategyArmoryTest - The following 1 profile is active: "dev" +25-03-03.23:16:08.184 [main ] INFO RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +25-03-03.23:16:08.186 [main ] INFO RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +25-03-03.23:16:08.214 [main ] INFO RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 16 ms. Found 0 Redis repository interfaces. +25-03-03.23:16:09.432 [main ] INFO Version - Redisson 3.23.4 +25-03-03.23:16:09.894 [redisson-netty-2-4] INFO MasterPubSubConnectionPool - 1 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:16:09.914 [redisson-netty-2-13] INFO MasterConnectionPool - 5 connections initialized for 192.168.1.10/192.168.1.10:6379 +25-03-03.23:16:11.278 [main ] INFO EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '/actuator' +25-03-03.23:16:11.330 [main ] INFO StrategyArmoryTest - Started StrategyArmoryTest in 4.566 seconds (JVM running for 5.677) +25-03-03.23:16:11.810 [main ] INFO StrategyArmoryTest - 测试:101 +25-03-03.23:16:11.813 [main ] INFO StrategyArmoryTest - 测试:101 +25-03-03.23:16:11.817 [main ] INFO StrategyArmoryTest - 测试:101 diff --git a/xfg-frame-archetype-lite-app/pom.xml b/xfg-frame-archetype-lite-app/pom.xml index e96799dfa530589136e1c1d144b2f095b8664144..fd22de5f26c9103c8747a38fb689bcf53e64c8c8 100644 --- a/xfg-frame-archetype-lite-app/pom.xml +++ b/xfg-frame-archetype-lite-app/pom.xml @@ -12,6 +12,10 @@ jar + + org.redisson + redisson-spring-boot-starter + org.springframework.boot spring-boot-starter-web diff --git a/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfig.java b/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..d3aa16685212b790b0e14a773de4e5c924e26df9 --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfig.java @@ -0,0 +1,85 @@ +package cn.bugstack.config; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.client.codec.BaseCodec; +import org.redisson.client.protocol.Decoder; +import org.redisson.client.protocol.Encoder; +import org.redisson.codec.JsonJacksonCodec; +import org.redisson.config.Config; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.IOException; + +/** + * Redis 客户端,使用 Redisson Redisson + * + * + */ +@Configuration +@EnableConfigurationProperties(RedisClientConfigProperties.class) +public class RedisClientConfig { + + @Bean("redissonClient") + public RedissonClient redissonClient(ConfigurableApplicationContext applicationContext, RedisClientConfigProperties properties) { + Config config = new Config(); + // 根据需要可以设定编解码器;https://github.com/redisson/redisson/wiki/4.-%E6%95%B0%E6%8D%AE%E5%BA%8F%E5%88%97%E5%8C%96 + config.setCodec(JsonJacksonCodec.INSTANCE); + + config.useSingleServer() + .setAddress("redis://" + properties.getHost() + ":" + properties.getPort()) +// .setPassword(properties.getPassword()) + .setConnectionPoolSize(properties.getPoolSize()) + .setConnectionMinimumIdleSize(properties.getMinIdleSize()) + .setIdleConnectionTimeout(properties.getIdleTimeout()) + .setConnectTimeout(properties.getConnectTimeout()) + .setRetryAttempts(properties.getRetryAttempts()) + .setRetryInterval(properties.getRetryInterval()) + .setPingConnectionInterval(properties.getPingInterval()) + .setKeepAlive(properties.isKeepAlive()) + ; + + return Redisson.create(config); + } + + static class RedisCodec extends BaseCodec { + + private final Encoder encoder = in -> { + ByteBuf out = ByteBufAllocator.DEFAULT.buffer(); + try { + ByteBufOutputStream os = new ByteBufOutputStream(out); + JSON.writeJSONString(os, in, SerializerFeature.WriteClassName); + return os.buffer(); + } catch (IOException e) { + out.release(); + throw e; + } catch (Exception e) { + out.release(); + throw new IOException(e); + } + }; + + private final Decoder decoder = (buf, state) -> JSON.parseObject(new ByteBufInputStream(buf), Object.class); + + @Override + public Decoder getValueDecoder() { + return decoder; + } + + @Override + public Encoder getValueEncoder() { + return encoder; + } + + } + +} diff --git a/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfigProperties.java b/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfigProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..1a77cfe051d96406699542c1a8c09db4fcf00786 --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/main/java/cn/bugstack/config/RedisClientConfigProperties.java @@ -0,0 +1,38 @@ +package cn.bugstack.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * + * @description Redis 连接配置 redisson-spring-boot-starter + * + */ +@Data +@ConfigurationProperties(prefix = "redis.sdk.config", ignoreInvalidFields = true) +public class RedisClientConfigProperties { + + /** host:ip */ + private String host; + /** 端口 */ + private int port; + /** 账密 */ + private String password; + /** 设置连接池的大小,默认为64 */ + private int poolSize = 64; + /** 设置连接池的最小空闲连接数,默认为10 */ + private int minIdleSize = 10; + /** 设置连接的最大空闲时间(单位:毫秒),超过该时间的空闲连接将被关闭,默认为10000 */ + private int idleTimeout = 10000; + /** 设置连接超时时间(单位:毫秒),默认为10000 */ + private int connectTimeout = 10000; + /** 设置连接重试次数,默认为3 */ + private int retryAttempts = 3; + /** 设置连接重试的间隔时间(单位:毫秒),默认为1000 */ + private int retryInterval = 1000; + /** 设置定期检查连接是否可用的时间间隔(单位:毫秒),默认为0,表示不进行定期检查 */ + private int pingInterval = 0; + /** 设置是否保持长连接,默认为true */ + private boolean keepAlive = true; + +} diff --git a/xfg-frame-archetype-lite-app/src/main/resources/application-dev.yml b/xfg-frame-archetype-lite-app/src/main/resources/application-dev.yml index b0e852490a7f9abc21dbc02e06c2637f9541ec74..2281e84833cf53e7b1dac73fd2608ef36309956e 100644 --- a/xfg-frame-archetype-lite-app/src/main/resources/application-dev.yml +++ b/xfg-frame-archetype-lite-app/src/main/resources/application-dev.yml @@ -34,6 +34,21 @@ mybatis: mapper-locations: classpath:/mybatis/mapper/*.xml config-location: classpath:/mybatis/config/mybatis-config.xml +# Redis +redis: + sdk: + config: + host: 192.168.1.10 + port: 6379 + pool-size: 10 + min-idle-size: 5 + idle-timeout: 30000 + connect-timeout: 5000 + retry-attempts: 3 + retry-interval: 1000 + ping-interval: 60000 + keep-alive: true + # 日志 logging: level: diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java index 9bc1a201d91950bc85a3ad92354618d6b3c5f2a0..10a5073a86090c4a13db59551d3d94eff3bf44fe 100644 --- a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java @@ -1,19 +1,30 @@ package cn.bugstack.test; +import cn.bugstack.infrastructure.redis.IRedisService; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; +import org.redisson.api.RMap; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import javax.annotation.Resource; + @Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class ApiTest { + + @Resource + private IRedisService redisService; + @Test - public void test() { - log.info("测试完成"); + public void test(){ + RMap map=redisService.getMap("stategy_id_100001"); + map.put(1,100); + map.put(2,101); + log.info("测试结果:{}",redisService.getFromMap("stategy_id_100001",1).toString()); } } diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyArmoryTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyArmoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..754fca62ab35a0fadb45ea987a3154879f8ef6a6 --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyArmoryTest.java @@ -0,0 +1,38 @@ +package cn.bugstack.test.domain; + +import cn.bugstack.domain.strategy.service.armory.IStrategyArmory; +import cn.bugstack.infrastructure.dao.IStrategyAwardDao; +import cn.bugstack.infrastructure.redis.IRedisService; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.redisson.api.RMap; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class StrategyArmoryTest { + + + @Resource + private IStrategyArmory strategyArmory; + + @Test + public void test(){ + boolean success=strategyArmory.assembleLotteryStrategy(100001l); + } + + @Test + public void test_getRandomAward(){ + log.info("测试:{}", strategyArmory.getRandomAwardId(100001l)); + log.info("测试:{}", strategyArmory.getRandomAwardId(100001l)); + log.info("测试:{}", strategyArmory.getRandomAwardId(100001l)); + + + } + +} \ No newline at end of file diff --git a/xfg-frame-archetype-lite-domain/pom.xml b/xfg-frame-archetype-lite-domain/pom.xml index 16c19e0481df286677e1890287e72c74e7dbd970..74a58317e03a7bf4831cf64250b750190b290de3 100644 --- a/xfg-frame-archetype-lite-domain/pom.xml +++ b/xfg-frame-archetype-lite-domain/pom.xml @@ -10,6 +10,10 @@ xfg-frame-archetype-lite-domain + + org.redisson + redisson-spring-boot-starter + org.projectlombok lombok diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..bf59ab0d32648274fb8a128453933ecd66fd9559 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java @@ -0,0 +1,37 @@ +package cn.bugstack.domain.strategy.model.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class StrategyAwardEntity { + /** 抽奖策略ID */ + private Long strategyId; + /** 抽奖奖品ID - 内部流转使用 */ + private Integer awardId; + /** 抽奖奖品标题 */ + private String awardTitle; + /** 抽奖奖品副标题 */ + private String awardSubtitle; + /** 奖品库存总量 */ + private Integer awardCount; + /** 奖品库存剩余 */ + private Integer awardCountSurplus; + /** 奖品中奖概率 */ + private BigDecimal awardRate; + /** 排序 */ + private Integer sort; + /** 规则模型,rule配置的模型同步到此表,便于使用 */ + private String ruleModels; + + + + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..f338a0c40ce89fa4b25bf65fd8f97999333ed5c4 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java @@ -0,0 +1,177 @@ +package cn.bugstack.domain.strategy.repository; + + + +import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @description 策略服务仓储接口 + */ +public interface IStrategyRepository { + List queryStrategyAwardList(Long strategyId); + + void storeStrategyAwardSearchRateTable(Long strategyId, int size, Map shuffleStrategyAwardSearchRateTable); + + int getRateRange(Long strategyId); + + Integer getStrategyAwardAssemble(Long strategyId, Integer rateKey); + +// List queryStrategyAwardList(Long strategyId); +// +// void storeStrategyAwardSearchRateTable(String key, Integer rateRange, Map strategyAwardSearchRateTable); +// +// Map getMap(String key); +// +// Integer getStrategyAwardAssemble(String key, Integer rateKey); +// +// int getRateRange(Long strategyId); +// +// int getRateRange(String key); +// +// StrategyEntity queryStrategyEntityByStrategyId(Long strategyId); +// +// StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel); +// +// String queryStrategyRuleValue(Long strategyId, String ruleModel); +// +// String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel); +// +// StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId); +// +// /** +// * 根据规则树ID,查询树结构信息 +// * +// * @param treeId 规则树ID +// * @return 树结构信息 +// */ +// RuleTreeVO queryRuleTreeVOByTreeId(String treeId); +// +// /** +// * 缓存奖品库存 +// * +// * @param cacheKey key +// * @param awardCount 库存值 +// */ +// void cacheStrategyAwardCount(String cacheKey, Integer awardCount); +// +// /** +// * 缓存key,decr 方式扣减库存 +// * +// * @param cacheKey 缓存Key +// * @return 扣减结果 +// */ +// Boolean subtractionAwardStock(String cacheKey); +// +// /** +// * 缓存key,decr 方式扣减库存 +// * +// * @param cacheKey 缓存Key +// * @param endDateTime 活动结束时间 +// * @return 扣减结果 +// */ +// Boolean subtractionAwardStock(String cacheKey, Date endDateTime); +// +// /** +// * 写入奖品库存消费队列 +// * +// * @param strategyAwardStockKeyVO 对象值对象 +// */ +// void awardStockConsumeSendQueue(StrategyAwardStockKeyVO strategyAwardStockKeyVO); +// +// /** +// * 获取奖品库存消费队列 +// */ +// StrategyAwardStockKeyVO takeQueueValue() throws InterruptedException; +// +// /** +// * 获取奖品库存消费队列 +// */ +// StrategyAwardStockKeyVO takeQueueValue(Long strategyId, Integer awardId) throws InterruptedException; +// +// /** +// * 更新奖品库存消耗 +// * +// * @param strategyId 策略ID +// * @param awardId 奖品ID +// */ +// void updateStrategyAwardStock(Long strategyId, Integer awardId); +// +// /** +// * 根据策略ID+奖品ID的唯一值组合,查询奖品信息 +// * +// * @param strategyId 策略ID +// * @param awardId 奖品ID +// * @return 奖品信息 +// */ +// StrategyAwardEntity queryStrategyAwardEntity(Long strategyId, Integer awardId); +// +// /** +// * 查询策略ID +// * +// * @param activityId 活动ID +// * @return 策略ID +// */ +// Long queryStrategyIdByActivityId(Long activityId); +// +// /** +// * 查询用户抽奖次数 - 当天的;策略ID:活动ID 1:1 的配置,可以直接用 strategyId 查询。 +// * +// * @param userId 用户ID +// * @param strategyId 策略ID +// * @return 用户今日参与次数 +// */ +// Integer queryTodayUserRaffleCount(String userId, Long strategyId); +// +// /** +// * 根据规则树ID集合查询奖品中加锁数量的配置「部分奖品需要抽奖N次解锁」 +// * +// * @param treeIds 规则树ID值 +// * @return key 规则树,value rule_lock 加锁值 +// */ +// Map queryAwardRuleLockCount(String[] treeIds); +// +// /** +// * 根据用户ID、策略ID,查询用户活动账户总使用量 +// * +// * @param userId 用户ID +// * @param strategyId 策略ID +// * @return 使用总量 +// */ +// Integer queryActivityAccountTotalUseCount(String userId, Long strategyId); +// +// /** +// * 查询奖品权重配置 +// * +// * @param strategyId 策略ID +// * @return 权重规则 +// */ +// List queryAwardRuleWeight(Long strategyId); +// +// /** +// * 查询有效活动的奖品配置 +// * +// * @return 奖品配置列表 +// */ +// List queryOpenActivityStrategyAwardList(); +// +// /** +// * 存储抽奖策略对应的Bean算法 +// * +// * @param key 策略ID +// * @param beanName 策略对象名称 +// */ +// void cacheStrategyArmoryAlgorithm(String key, String beanName); +// +// /** +// * 获取存储抽奖策略对应的Bean算法 +// * +// * @param key 策略ID +// * @return 策略对象名称 +// */ +// String queryStrategyArmoryAlgorithmFromCache(String key); + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java new file mode 100644 index 0000000000000000000000000000000000000000..a13ae12218c733ff9edff9cba112c6860ec97f05 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java @@ -0,0 +1,26 @@ +package cn.bugstack.domain.strategy.service.armory; + +/** + * @description 策略装配库(兵工厂),负责初始化策略计算 + */ +public interface IStrategyArmory { + + /** + * 装配抽奖策略配置「触发的时机可以为活动审核通过后进行调用」 + * + * @param strategyId 策略ID + * @return 装配结果 + */ + boolean assembleLotteryStrategy(Long strategyId); + + + /** + * 获取抽奖策略装配的随机结果 + * + * @param strategyId 策略ID + * @return 抽奖结果 + */ + Integer getRandomAwardId(Long strategyId); + + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java new file mode 100644 index 0000000000000000000000000000000000000000..f62aff04dd46cae04e3be97175db6cd301e43525 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java @@ -0,0 +1,79 @@ +package cn.bugstack.domain.strategy.service.armory; + +import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; +import cn.bugstack.domain.strategy.repository.IStrategyRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.security.SecureRandom; +import java.util.Collections; +import java.util.*; + +/** + * @desciption 策略装配库 + */ +@Slf4j +@Service +public class StrategyArmory implements IStrategyArmory { + + @Resource + private IStrategyRepository repository; + + @Override + public boolean assembleLotteryStrategy(Long strategyId) { + //取得了配置实体类 + List strategyAwardEntities=repository.queryStrategyAwardList(strategyId); + + //最小的概率 + BigDecimal minAwardRate=strategyAwardEntities.stream() + .map(StrategyAwardEntity :: getAwardRate) + .min(BigDecimal::compareTo) + .orElse(BigDecimal.ZERO); + //总的值 + + BigDecimal totalAwardRate=strategyAwardEntities.stream() + .map(StrategyAwardEntity::getAwardRate) + .reduce(BigDecimal.ZERO,BigDecimal::add); + + BigDecimal rateRage=totalAwardRate.divide(minAwardRate,0, RoundingMode.CEILING); + + // 5. 生成策略奖品概率查找表「这里指需要在list集合中,存放上对应的奖品占位即可,占位越多等于概率越高」 + List strategyAwardSearchRateTables = new ArrayList<>(rateRage.intValue()); + for (StrategyAwardEntity strategyAward : strategyAwardEntities) { + Integer awardId = strategyAward.getAwardId(); + BigDecimal awardRate = strategyAward.getAwardRate(); + // 计算出每个概率值需要存放到查找表的数量,循环填充 + for (int i = 0; i < rateRage.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue(); i++) { + strategyAwardSearchRateTables.add(awardId); + } + } + + // 6. 对存储的奖品进行乱序操作 + Collections.shuffle(strategyAwardSearchRateTables); + + // 7. 生成出Map集合,key值,对应的就是后续的概率值。通过概率来获得对应的奖品ID + Map shuffleStrategyAwardSearchRateTable = new LinkedHashMap<>(); + for (int i = 0; i < strategyAwardSearchRateTables.size(); i++) { + shuffleStrategyAwardSearchRateTable.put(i, strategyAwardSearchRateTables.get(i)); + } + + // 8. 存放到 Redis + repository.storeStrategyAwardSearchRateTable(strategyId, shuffleStrategyAwardSearchRateTable.size(), shuffleStrategyAwardSearchRateTable); + + return true; + } + + @Override + public Integer getRandomAwardId(Long strategyId) { + // 分布式部署下,不一定为当前应用做的策略装配。也就是值不一定会保存到本应用,而是分布式应用,所以需要从 Redis 中获取。 + int rateRange = repository.getRateRange(strategyId); + // 通过生成的随机值,获取概率值奖品查找表的结果 + return repository.getStrategyAwardAssemble(strategyId, new SecureRandom().nextInt(rateRange)); + + } + + +} diff --git a/xfg-frame-archetype-lite-infrastructure/pom.xml b/xfg-frame-archetype-lite-infrastructure/pom.xml index 2bb0475805526ef6a7f55d6b32a067a5e174bfc9..f7f52dbbc312911f05bd1a0390ccc435420f4890 100644 --- a/xfg-frame-archetype-lite-infrastructure/pom.xml +++ b/xfg-frame-archetype-lite-infrastructure/pom.xml @@ -18,11 +18,17 @@ org.projectlombok lombok + + org.redisson + redisson-spring-boot-starter + + cn.bugstack xfg-frame-archetype-lite-domain + diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/adapter/repository/StrategyRepository.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/adapter/repository/StrategyRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..517cfc6cf551216bc0abe2b22f2376e1f2ed019b --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/adapter/repository/StrategyRepository.java @@ -0,0 +1,473 @@ +package cn.bugstack.infrastructure.adapter.repository; + +import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; +import cn.bugstack.domain.strategy.repository.IStrategyRepository; +import cn.bugstack.infrastructure.dao.IStrategyAwardDao; +import cn.bugstack.infrastructure.dao.IStrategyDao; +import cn.bugstack.infrastructure.dao.IStrategyRuleDao; +import cn.bugstack.infrastructure.dao.po.Strategy; +import cn.bugstack.infrastructure.dao.po.StrategyAward; +import cn.bugstack.infrastructure.dao.po.StrategyRule; +import cn.bugstack.infrastructure.redis.IRedisService; +import cn.bugstack.types.common.Constants; +import cn.bugstack.types.exception.AppException; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RBlockingQueue; +import org.redisson.api.RDelayedQueue; +import org.springframework.stereotype.Repository; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + + +/** + * @description 策略服务仓储实现 + */ +@Slf4j +@Repository +public class StrategyRepository implements IStrategyRepository { + + @Resource + private IStrategyAwardDao strategyAwardDao; + + +// @Resource +// private IRaffleActivityDao raffleActivityDao; +// @Resource +// private IStrategyDao strategyDao; +// @Resource +// private IStrategyRuleDao strategyRuleDao; + +// @Resource +// private IRaffleActivityAccountDao raffleActivityAccountDao; +// @Resource +// private IRaffleActivityAccountDayDao raffleActivityAccountDayDao; + @Resource + private IRedisService redisService; +// @Resource +// private IRuleTreeDao ruleTreeDao; +// @Resource +// private IRuleTreeNodeDao ruleTreeNodeDao; +// @Resource +// private IRuleTreeNodeLineDao ruleTreeNodeLineDao; +// + @Override + public List queryStrategyAwardList(Long strategyId) { + // 优先从缓存获取 + String cacheKey = Constants.RedisKey.STRATEGY_AWARD_LIST_KEY + strategyId; + + List strategyAwardEntities = redisService.getValue(cacheKey); + + if (null != strategyAwardEntities && !strategyAwardEntities.isEmpty()) return strategyAwardEntities; + // 从库中获取数据 + List strategyAwards = strategyAwardDao.queryStrategyAwardListByStrategyId(strategyId); + strategyAwardEntities = new ArrayList<>(strategyAwards.size()); + for (StrategyAward strategyAward : strategyAwards) { + StrategyAwardEntity strategyAwardEntity = StrategyAwardEntity.builder() + .strategyId(strategyAward.getStrategyId()) + .awardId(strategyAward.getAwardId()) + .awardTitle(strategyAward.getAwardTitle()) + .awardSubtitle(strategyAward.getAwardSubtitle()) + .awardCount(strategyAward.getAwardCount()) + .awardCountSurplus(strategyAward.getAwardCountSurplus()) + .awardRate(strategyAward.getAwardRate()) + .sort(strategyAward.getSort()) + .ruleModels(strategyAward.getRuleModels()) + .build(); + strategyAwardEntities.add(strategyAwardEntity); + } + redisService.setValue(cacheKey, strategyAwardEntities); + return strategyAwardEntities; + } + + + + /** + * 在 Redisson 中,当你调用 getMap 方法时,如果指定的 key 不存在,Redisson 并不会立即在 Redis 数据库中创建这个 key。相反,它会返回一个 RMap 对象的实例,这个实例是一个本地的 Java 对象,它代表了 Redis 中的一个哈希(hash)。 + *

+ * 当你开始使用这个 RMap 实例进行操作,比如添加键值对,那么 Redisson 会在 Redis 数据库中创建相应的 key,并将数据存储在这个 key 对应的哈希中。如果你只是获取了 RMap 实例而没有进行任何操作,那么在 Redis 数据库中是不会有任何变化的。 + *

+ * 简单来说,getMap 方法返回的 RMap 对象是懒加载的,只有在你实际进行操作时,Redis 数据库中的数据结构才会被创建或修改。 + */ + @Override + public void storeStrategyAwardSearchRateTable(Long strategyId, int size, Map shuffleStrategyAwardSearchRateTable) { + // 1. 存储抽奖策略范围值,如10000,用于生成1000以内的随机数 + redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId, size); + // 2. 存储概率查找表 + Map cacheRateTable = redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId); + cacheRateTable.putAll(shuffleStrategyAwardSearchRateTable); + + } + + @Override + public int getRateRange(Long strategyId) { + return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId); + } + + @Override + public Integer getStrategyAwardAssemble(Long strategyId, Integer rateKey) { + return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId,rateKey); + } + + +// +// @Override +// public Map getMap(String key) { +// return redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key); +// } +// +// @Override +// public Integer getStrategyAwardAssemble(String key, Integer rateKey) { +// return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key, rateKey); +// } +// +// @Override +// public int getRateRange(Long strategyId) { +// return getRateRange(String.valueOf(strategyId)); +// } +// +// @Override +// public int getRateRange(String key) { +// String cacheKey = Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key; +// if (!redisService.isExists(cacheKey)) { +// throw new AppException(UN_ASSEMBLED_STRATEGY_ARMORY.getCode(), cacheKey + Constants.COLON + UN_ASSEMBLED_STRATEGY_ARMORY.getInfo()); +// } +// return redisService.getValue(cacheKey); +// } +// +// @Override +// public StrategyEntity queryStrategyEntityByStrategyId(Long strategyId) { +// // 优先从缓存获取 +// String cacheKey = Constants.RedisKey.STRATEGY_KEY + strategyId; +// StrategyEntity strategyEntity = redisService.getValue(cacheKey); +// if (null != strategyEntity) return strategyEntity; +// Strategy strategy = strategyDao.queryStrategyByStrategyId(strategyId); +// if (null == strategy) return StrategyEntity.builder().build(); +// strategyEntity = StrategyEntity.builder() +// .strategyId(strategy.getStrategyId()) +// .strategyDesc(strategy.getStrategyDesc()) +// .ruleModels(strategy.getRuleModels()) +// .build(); +// redisService.setValue(cacheKey, strategyEntity); +// return strategyEntity; +// } +// +// @Override +// public StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel) { +// StrategyRule strategyRuleReq = new StrategyRule(); +// strategyRuleReq.setStrategyId(strategyId); +// strategyRuleReq.setRuleModel(ruleModel); +// StrategyRule strategyRuleRes = strategyRuleDao.queryStrategyRule(strategyRuleReq); +// if (null == strategyRuleRes) return null; +// return StrategyRuleEntity.builder() +// .strategyId(strategyRuleRes.getStrategyId()) +// .awardId(strategyRuleRes.getAwardId()) +// .ruleType(strategyRuleRes.getRuleType()) +// .ruleModel(strategyRuleRes.getRuleModel()) +// .ruleValue(strategyRuleRes.getRuleValue()) +// .ruleDesc(strategyRuleRes.getRuleDesc()) +// .build(); +// } +// +// @Override +// public String queryStrategyRuleValue(Long strategyId, String ruleModel) { +// return queryStrategyRuleValue(strategyId, null, ruleModel); +// } +// +// @Override +// public String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel) { +// StrategyRule strategyRule = new StrategyRule(); +// strategyRule.setStrategyId(strategyId); +// strategyRule.setAwardId(awardId); +// strategyRule.setRuleModel(ruleModel); +// return strategyRuleDao.queryStrategyRuleValue(strategyRule); +// } +// +// @Override +// public StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId) { +// StrategyAward strategyAward = new StrategyAward(); +// strategyAward.setStrategyId(strategyId); +// strategyAward.setAwardId(awardId); +// String ruleModels = strategyAwardDao.queryStrategyAwardRuleModels(strategyAward); +// if (null == ruleModels) return null; +// return StrategyAwardRuleModelVO.builder().ruleModels(ruleModels).build(); +// } +// +// @Override +// public RuleTreeVO queryRuleTreeVOByTreeId(String treeId) { +// // 优先从缓存获取 +// String cacheKey = Constants.RedisKey.RULE_TREE_VO_KEY + treeId; +// RuleTreeVO ruleTreeVOCache = redisService.getValue(cacheKey); +// if (null != ruleTreeVOCache) return ruleTreeVOCache; +// +// // 从数据库获取 +// RuleTree ruleTree = ruleTreeDao.queryRuleTreeByTreeId(treeId); +// List ruleTreeNodes = ruleTreeNodeDao.queryRuleTreeNodeListByTreeId(treeId); +// List ruleTreeNodeLines = ruleTreeNodeLineDao.queryRuleTreeNodeLineListByTreeId(treeId); +// +// // 1. tree node line 转换Map结构 +// Map> ruleTreeNodeLineMap = new HashMap<>(); +// for (RuleTreeNodeLine ruleTreeNodeLine : ruleTreeNodeLines) { +// RuleTreeNodeLineVO ruleTreeNodeLineVO = RuleTreeNodeLineVO.builder() +// .treeId(ruleTreeNodeLine.getTreeId()) +// .ruleNodeFrom(ruleTreeNodeLine.getRuleNodeFrom()) +// .ruleNodeTo(ruleTreeNodeLine.getRuleNodeTo()) +// .ruleLimitType(RuleLimitTypeVO.valueOf(ruleTreeNodeLine.getRuleLimitType())) +// .ruleLimitValue(RuleLogicCheckTypeVO.valueOf(ruleTreeNodeLine.getRuleLimitValue())) +// .build(); +// +// ruleTreeNodeLineMap +// .computeIfAbsent(ruleTreeNodeLine.getRuleNodeFrom(), k -> new ArrayList<>()) +// .add(ruleTreeNodeLineVO); +// } +// +// // 2. tree node 转换为Map结构 +// Map treeNodeMap = new HashMap<>(); +// for (RuleTreeNode ruleTreeNode : ruleTreeNodes) { +// RuleTreeNodeVO ruleTreeNodeVO = RuleTreeNodeVO.builder() +// .treeId(ruleTreeNode.getTreeId()) +// .ruleKey(ruleTreeNode.getRuleKey()) +// .ruleDesc(ruleTreeNode.getRuleDesc()) +// .ruleValue(ruleTreeNode.getRuleValue()) +// .treeNodeLineVOList(ruleTreeNodeLineMap.get(ruleTreeNode.getRuleKey())) +// .build(); +// treeNodeMap.put(ruleTreeNode.getRuleKey(), ruleTreeNodeVO); +// } +// +// // 3. 构建 Rule Tree +// RuleTreeVO ruleTreeVODB = RuleTreeVO.builder() +// .treeId(ruleTree.getTreeId()) +// .treeName(ruleTree.getTreeName()) +// .treeDesc(ruleTree.getTreeDesc()) +// .treeRootRuleNode(ruleTree.getTreeRootRuleKey()) +// .treeNodeMap(treeNodeMap) +// .build(); +// +// redisService.setValue(cacheKey, ruleTreeVODB); +// return ruleTreeVODB; +// } +// +// @Override +// public void cacheStrategyAwardCount(String cacheKey, Integer awardCount) { +// if (redisService.isExists(cacheKey)) return; +// redisService.setAtomicLong(cacheKey, awardCount); +// } +// +// @Override +// public Boolean subtractionAwardStock(String cacheKey) { +// return subtractionAwardStock(cacheKey, null); +// } +// +// /** +// * 扣减库存并加锁操作,decr和0对比,如果是incr操作就和总量对比,和总量对比可以动态添加库存 +// * +// * @param cacheKey 缓存Key +// * @param endDateTime 活动结束时间 +// */ +// @Override +// public Boolean subtractionAwardStock(String cacheKey, Date endDateTime) { +// long surplus = redisService.decr(cacheKey); +// if (surplus < 0) { +// // 库存小于0,恢复为0个 +// redisService.setAtomicLong(cacheKey, 0); +// return false; +// } +// // 1. 按照cacheKey decr 后的值,如 99、98、97 和 key 组成为库存锁的key进行使用。 +// // 2. 加锁为了兜底,如果后续有恢复库存,手动处理等,也不会超卖。因为所有的可用库存key,都被加锁了。 +// String lockKey = cacheKey + Constants.UNDERLINE + surplus; +// Boolean lock = false; +// if (null != endDateTime) { +// long expireMillis = endDateTime.getTime() - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1); +// lock = redisService.setNx(lockKey, expireMillis, TimeUnit.MILLISECONDS); +// } else { +// lock = redisService.setNx(lockKey); +// } +// if (!lock) { +// log.info("策略奖品库存加锁失败 {}", lockKey); +// } +// return lock; +// } +// +// @Override +// public void awardStockConsumeSendQueue(StrategyAwardStockKeyVO strategyAwardStockKeyVO) { +// String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_QUERY_KEY + Constants.UNDERLINE + strategyAwardStockKeyVO.getStrategyId() + Constants.UNDERLINE + strategyAwardStockKeyVO.getAwardId(); +// RBlockingQueue blockingQueue = redisService.getBlockingQueue(cacheKey); +// RDelayedQueue delayedQueue = redisService.getDelayedQueue(blockingQueue); +// delayedQueue.offer(strategyAwardStockKeyVO, 3, TimeUnit.SECONDS); +// } +// +// @Override +// public StrategyAwardStockKeyVO takeQueueValue() throws InterruptedException { +// String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_QUERY_KEY; +// RBlockingQueue destinationQueue = redisService.getBlockingQueue(cacheKey); +// return destinationQueue.poll(); +// } +// +// @Override +// public StrategyAwardStockKeyVO takeQueueValue(Long strategyId, Integer awardId) throws InterruptedException { +// String cacheKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_QUERY_KEY + Constants.UNDERLINE + strategyId + Constants.UNDERLINE + awardId; +// RBlockingQueue destinationQueue = redisService.getBlockingQueue(cacheKey); +// return destinationQueue.poll(); +// } +// +// @Override +// public void updateStrategyAwardStock(Long strategyId, Integer awardId) { +// StrategyAward strategyAward = new StrategyAward(); +// strategyAward.setStrategyId(strategyId); +// strategyAward.setAwardId(awardId); +// strategyAwardDao.updateStrategyAwardStock(strategyAward); +// } +// +// @Override +// public StrategyAwardEntity queryStrategyAwardEntity(Long strategyId, Integer awardId) { +// // 优先从缓存获取 +// String cacheKey = Constants.RedisKey.STRATEGY_AWARD_KEY + strategyId + Constants.UNDERLINE + awardId; +// StrategyAwardEntity strategyAwardEntity = redisService.getValue(cacheKey); +// if (null != strategyAwardEntity) return strategyAwardEntity; +// // 查询数据 +// StrategyAward strategyAwardReq = new StrategyAward(); +// strategyAwardReq.setStrategyId(strategyId); +// strategyAwardReq.setAwardId(awardId); +// StrategyAward strategyAwardRes = strategyAwardDao.queryStrategyAward(strategyAwardReq); +// // 转换数据 +// strategyAwardEntity = StrategyAwardEntity.builder() +// .strategyId(strategyAwardRes.getStrategyId()) +// .awardId(strategyAwardRes.getAwardId()) +// .awardTitle(strategyAwardRes.getAwardTitle()) +// .awardSubtitle(strategyAwardRes.getAwardSubtitle()) +// .awardCount(strategyAwardRes.getAwardCount()) +// .awardCountSurplus(strategyAwardRes.getAwardCountSurplus()) +// .awardRate(strategyAwardRes.getAwardRate()) +// .sort(strategyAwardRes.getSort()) +// .build(); +// // 缓存结果 +// redisService.setValue(cacheKey, strategyAwardEntity); +// // 返回数据 +// return strategyAwardEntity; +// } +// +// @Override +// public Long queryStrategyIdByActivityId(Long activityId) { +// return raffleActivityDao.queryStrategyIdByActivityId(activityId); +// } +// +// @Override +// public Integer queryTodayUserRaffleCount(String userId, Long strategyId) { +// // 活动ID +// Long activityId = raffleActivityDao.queryActivityIdByStrategyId(strategyId); +// // 封装参数 +// RaffleActivityAccountDay raffleActivityAccountDayReq = new RaffleActivityAccountDay(); +// raffleActivityAccountDayReq.setUserId(userId); +// raffleActivityAccountDayReq.setActivityId(activityId); +// raffleActivityAccountDayReq.setDay(RaffleActivityAccountDay.currentDay()); +// RaffleActivityAccountDay raffleActivityAccountDay = raffleActivityAccountDayDao.queryActivityAccountDayByUserId(raffleActivityAccountDayReq); +// if (null == raffleActivityAccountDay) return 0; +// // 总次数 - 剩余的,等于今日参与的 +// return raffleActivityAccountDay.getDayCount() - raffleActivityAccountDay.getDayCountSurplus(); +// } +// +// @Override +// public Map queryAwardRuleLockCount(String[] treeIds) { +// if (null == treeIds || treeIds.length == 0) return new HashMap<>(); +// List ruleTreeNodes = ruleTreeNodeDao.queryRuleLocks(treeIds); +// Map resultMap = new HashMap<>(); +// for (RuleTreeNode node : ruleTreeNodes) { +// String treeId = node.getTreeId(); +// Integer ruleValue = Integer.valueOf(node.getRuleValue()); +// resultMap.put(treeId, ruleValue); +// } +// return resultMap; +// } +// +// @Override +// public Integer queryActivityAccountTotalUseCount(String userId, Long strategyId) { +// Long activityId = raffleActivityDao.queryActivityIdByStrategyId(strategyId); +// RaffleActivityAccount raffleActivityAccount = raffleActivityAccountDao.queryActivityAccountByUserId(RaffleActivityAccount.builder() +// .userId(userId) +// .activityId(activityId) +// .build()); +// // 返回计算使用量 +// return raffleActivityAccount.getTotalCount() - raffleActivityAccount.getTotalCountSurplus(); +// } +// +// @Override +// public List queryAwardRuleWeight(Long strategyId) { +// // 优先从缓存获取 +// String cacheKey = Constants.RedisKey.STRATEGY_RULE_WEIGHT_KEY + strategyId; +// List ruleWeightVOS = redisService.getValue(cacheKey); +// if (null != ruleWeightVOS) return ruleWeightVOS; +// +// ruleWeightVOS = new ArrayList<>(); +// // 1. 查询权重规则配置 +// StrategyRule strategyRuleReq = new StrategyRule(); +// strategyRuleReq.setStrategyId(strategyId); +// strategyRuleReq.setRuleModel(DefaultChainFactory.LogicModel.RULE_WEIGHT.getCode()); +// String ruleValue = strategyRuleDao.queryStrategyRuleValue(strategyRuleReq); +// // 2. 借助实体对象转换规则 +// StrategyRuleEntity strategyRuleEntity = new StrategyRuleEntity(); +// strategyRuleEntity.setRuleModel(DefaultChainFactory.LogicModel.RULE_WEIGHT.getCode()); +// strategyRuleEntity.setRuleValue(ruleValue); +// Map> ruleWeightValues = strategyRuleEntity.getRuleWeightValues(); +// // 3. 遍历规则组装奖品配置 +// Set ruleWeightKeys = ruleWeightValues.keySet(); +// for (String ruleWeightKey : ruleWeightKeys) { +// List awardIds = ruleWeightValues.get(ruleWeightKey); +// List awardList = new ArrayList<>(); +// // 也可以修改为一次从数据库查询 +// for (Integer awardId : awardIds) { +// StrategyAward strategyAwardReq = new StrategyAward(); +// strategyAwardReq.setStrategyId(strategyId); +// strategyAwardReq.setAwardId(awardId); +// StrategyAward strategyAward = strategyAwardDao.queryStrategyAward(strategyAwardReq); +// awardList.add(RuleWeightVO.Award.builder() +// .awardId(strategyAward.getAwardId()) +// .awardTitle(strategyAward.getAwardTitle()) +// .build()); +// } +// +// ruleWeightVOS.add(RuleWeightVO.builder() +// .ruleValue(ruleValue) +// .weight(Integer.valueOf(ruleWeightKey.split(Constants.COLON)[0])) +// .awardIds(awardIds) +// .awardList(awardList) +// .build()); +// } +// +// // 设置缓存 - 实际场景中,这类数据,可以在活动下架的时候统一清空缓存。 +// redisService.setValue(cacheKey, ruleWeightVOS); +// +// return ruleWeightVOS; +// } +// +// @Override +// public List queryOpenActivityStrategyAwardList() { +// List strategyAwards = strategyAwardDao.queryOpenActivityStrategyAwardList(); +// if (null == strategyAwards || strategyAwards.isEmpty()) return null; +// +// List strategyAwardStockKeyVOS = new ArrayList<>(); +// for (StrategyAward strategyAward : strategyAwards) { +// StrategyAwardStockKeyVO strategyAwardStockKeyVO = StrategyAwardStockKeyVO.builder() +// .strategyId(strategyAward.getStrategyId()) +// .awardId(strategyAward.getAwardId()) +// .build(); +// strategyAwardStockKeyVOS.add(strategyAwardStockKeyVO); +// } +// +// return strategyAwardStockKeyVOS; +// } +// +// @Override +// public void cacheStrategyArmoryAlgorithm(String key, String beanName) { +// String cacheKey = Constants.RedisKey.STRATEGY_ARMORY_ALGORITHM_KEY + key; +// redisService.setValue(cacheKey, beanName); +// } +// +// @Override +// public String queryStrategyArmoryAlgorithmFromCache(String key) { +// String cacheKey = Constants.RedisKey.STRATEGY_ARMORY_ALGORITHM_KEY + key; +// if (!redisService.isExists(cacheKey)) return null; +// return redisService.getValue(cacheKey); +// } + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/IRedisService.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/IRedisService.java new file mode 100644 index 0000000000000000000000000000000000000000..c048230b6cef159603591b9f5c9ea6ddfb5090d1 --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/IRedisService.java @@ -0,0 +1,266 @@ +package cn.bugstack.infrastructure.redis; + +import org.redisson.api.*; + +import java.util.concurrent.TimeUnit; + + +public interface IRedisService { + + /** + * 设置指定 key 的值 + * + * @param key 键 + * @param value 值 + */ + void setValue(String key, T value); + + /** + * 设置指定 key 的值 + * + * @param key 键 + * @param value 值 + * @param expired 过期时间 + */ + void setValue(String key, T value, long expired); + + /** + * 获取指定 key 的值 + * + * @param key 键 + * @return 值 + */ + T getValue(String key); + + /** + * 获取队列 + * + * @param key 键 + * @param 泛型 + * @return 队列 + */ + RQueue getQueue(String key); + + /** + * 加锁队列 + * + * @param key 键 + * @param 泛型 + * @return 队列 + */ + RBlockingQueue getBlockingQueue(String key); + + /** + * 延迟队列 + * + * @param rBlockingQueue 加锁队列 + * @param 泛型 + * @return 队列 + */ + RDelayedQueue getDelayedQueue(RBlockingQueue rBlockingQueue); + + /** + * 设置值 + * + * @param key key 键 + * @param value 值 + */ + void setAtomicLong(String key, long value); + + /** + * 获取值 + * + * @param key key 键 + */ + Long getAtomicLong(String key); + + /** + * 自增 Key 的值;1、2、3、4 + * + * @param key 键 + * @return 自增后的值 + */ + long incr(String key); + + /** + * 指定值,自增 Key 的值;1、2、3、4 + * + * @param key 键 + * @return 自增后的值 + */ + long incrBy(String key, long delta); + + /** + * 自减 Key 的值;1、2、3、4 + * + * @param key 键 + * @return 自增后的值 + */ + long decr(String key); + + /** + * 指定值,自增 Key 的值;1、2、3、4 + * + * @param key 键 + * @return 自增后的值 + */ + long decrBy(String key, long delta); + + + /** + * 移除指定 key 的值 + * + * @param key 键 + */ + void remove(String key); + + /** + * 判断指定 key 的值是否存在 + * + * @param key 键 + * @return true/false + */ + boolean isExists(String key); + + /** + * 将指定的值添加到集合中 + * + * @param key 键 + * @param value 值 + */ + void addToSet(String key, String value); + + /** + * 判断指定的值是否是集合的成员 + * + * @param key 键 + * @param value 值 + * @return 如果是集合的成员返回 true,否则返回 false + */ + boolean isSetMember(String key, String value); + + /** + * 将指定的值添加到列表中 + * + * @param key 键 + * @param value 值 + */ + void addToList(String key, String value); + + /** + * 获取列表中指定索引的值 + * + * @param key 键 + * @param index 索引 + * @return 值 + */ + String getFromList(String key, int index); + + /** + * 获取Map + * + * @param key 键 + * @return 值 + */ + RMap getMap(String key); + + /** + * 将指定的键值对添加到哈希表中 + * + * @param key 键 + * @param field 字段 + * @param value 值 + */ + void addToMap(String key, String field, String value); + + /** + * 获取哈希表中指定字段的值 + * + * @param key 键 + * @param field 字段 + * @return 值 + */ + String getFromMap(String key, String field); + + /** + * 获取哈希表中指定字段的值 + * + * @param key 键 + * @param field 字段 + * @return 值 + */ + V getFromMap(String key, K field); + + /** + * 将指定的值添加到有序集合中 + * + * @param key 键 + * @param value 值 + */ + void addToSortedSet(String key, String value); + + /** + * 获取 Redis 锁(可重入锁) + * + * @param key 键 + * @return Lock + */ + RLock getLock(String key); + + /** + * 获取 Redis 锁(公平锁) + * + * @param key 键 + * @return Lock + */ + RLock getFairLock(String key); + + /** + * 获取 Redis 锁(读写锁) + * + * @param key 键 + * @return RReadWriteLock + */ + RReadWriteLock getReadWriteLock(String key); + + /** + * 获取 Redis 信号量 + * + * @param key 键 + * @return RSemaphore + */ + RSemaphore getSemaphore(String key); + + /** + * 获取 Redis 过期信号量 + *

+ * 基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。 + * 同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。 + * + * @param key 键 + * @return RPermitExpirableSemaphore + */ + RPermitExpirableSemaphore getPermitExpirableSemaphore(String key); + + /** + * 闭锁 + * + * @param key 键 + * @return RCountDownLatch + */ + RCountDownLatch getCountDownLatch(String key); + + /** + * 布隆过滤器 + * + * @param key 键 + * @param 存放对象 + * @return 返回结果 + */ + RBloomFilter getBloomFilter(String key); + + Boolean setNx(String key); + + Boolean setNx(String key, long expired, TimeUnit timeUnit); + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/RedissonService.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/RedissonService.java new file mode 100644 index 0000000000000000000000000000000000000000..5175a39f4a7ae898ee10763005ee2cae6e0617ee --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/RedissonService.java @@ -0,0 +1,176 @@ +package cn.bugstack.infrastructure.redis; + +import org.redisson.api.*; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.concurrent.TimeUnit; + + +@Service("redissonService") +public class RedissonService implements IRedisService { + + @Resource + private RedissonClient redissonClient; + + public void setValue(String key, T value) { + redissonClient.getBucket(key).set(value); + } + + @Override + public void setValue(String key, T value, long expired) { + RBucket bucket = redissonClient.getBucket(key); + bucket.set(value, Duration.ofMillis(expired)); + } + + public T getValue(String key) { + return redissonClient.getBucket(key).get(); + } + + @Override + public RQueue getQueue(String key) { + return redissonClient.getQueue(key); + } + + @Override + public RBlockingQueue getBlockingQueue(String key) { + return redissonClient.getBlockingQueue(key); + } + + @Override + public RDelayedQueue getDelayedQueue(RBlockingQueue rBlockingQueue) { + return redissonClient.getDelayedQueue(rBlockingQueue); + } + + @Override + public void setAtomicLong(String key, long value) { + redissonClient.getAtomicLong(key).set(value); + } + + @Override + public Long getAtomicLong(String key) { + return redissonClient.getAtomicLong(key).get(); + } + + @Override + public long incr(String key) { + return redissonClient.getAtomicLong(key).incrementAndGet(); + } + + @Override + public long incrBy(String key, long delta) { + return redissonClient.getAtomicLong(key).addAndGet(delta); + } + + @Override + public long decr(String key) { + return redissonClient.getAtomicLong(key).decrementAndGet(); + } + + @Override + public long decrBy(String key, long delta) { + return redissonClient.getAtomicLong(key).addAndGet(-delta); + } + + @Override + public void remove(String key) { + redissonClient.getBucket(key).delete(); + } + + @Override + public boolean isExists(String key) { + return redissonClient.getBucket(key).isExists(); + } + + public void addToSet(String key, String value) { + RSet set = redissonClient.getSet(key); + set.add(value); + } + + public boolean isSetMember(String key, String value) { + RSet set = redissonClient.getSet(key); + return set.contains(value); + } + + public void addToList(String key, String value) { + RList list = redissonClient.getList(key); + list.add(value); + } + + public String getFromList(String key, int index) { + RList list = redissonClient.getList(key); + return list.get(index); + } + + @Override + public RMap getMap(String key) { + return redissonClient.getMap(key); + } + + public void addToMap(String key, String field, String value) { + RMap map = redissonClient.getMap(key); + map.put(field, value); + } + + public String getFromMap(String key, String field) { + RMap map = redissonClient.getMap(key); + return map.get(field); + } + + @Override + public V getFromMap(String key, K field) { + return redissonClient.getMap(key).get(field); + } + + public void addToSortedSet(String key, String value) { + RSortedSet sortedSet = redissonClient.getSortedSet(key); + sortedSet.add(value); + } + + @Override + public RLock getLock(String key) { + return redissonClient.getLock(key); + } + + @Override + public RLock getFairLock(String key) { + return redissonClient.getFairLock(key); + } + + @Override + public RReadWriteLock getReadWriteLock(String key) { + return redissonClient.getReadWriteLock(key); + } + + @Override + public RSemaphore getSemaphore(String key) { + return redissonClient.getSemaphore(key); + } + + @Override + public RPermitExpirableSemaphore getPermitExpirableSemaphore(String key) { + return redissonClient.getPermitExpirableSemaphore(key); + } + + @Override + public RCountDownLatch getCountDownLatch(String key) { + return redissonClient.getCountDownLatch(key); + } + + @Override + public RBloomFilter getBloomFilter(String key) { + return redissonClient.getBloomFilter(key); + } + + @Override + public Boolean setNx(String key) { + return redissonClient.getBucket(key).trySet("lock"); + } + + @Override + public Boolean setNx(String key, long expired, TimeUnit timeUnit) { + return redissonClient.getBucket(key).trySet("lock", expired, timeUnit); + } + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/package-info.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/package-info.java deleted file mode 100644 index 6c4af599f36b3ce3e4b4b9dd56a530470f9f1270..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/redis/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 提供redis链接配置 - */ -package cn.bugstack.infrastructure.redis; \ No newline at end of file diff --git a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java index 3e21a0d11d286581ba84b5545c78411809a745e9..1943758bae6ec35968ac3dc73f1278dbd3821b19 100644 --- a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java +++ b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java @@ -3,5 +3,35 @@ package cn.bugstack.types.common; public class Constants { public final static String SPLIT = ","; + public final static String COLON = ":"; + public final static String SPACE = " "; + public final static String UNDERLINE = "_"; + + /** + * 定义出缓存key的前缀标识, + */ + public static class RedisKey { + public static String ACTIVITY_KEY = "big_market_activity_key_"; + public static String ACTIVITY_SKU_KEY = "big_market_activity_sku_key_"; + public static String ACTIVITY_COUNT_KEY = "big_market_activity_count_key_"; + public static String STRATEGY_KEY = "big_market_strategy_key_"; + public static String STRATEGY_AWARD_KEY = "big_market_strategy_award_key_"; + public static String STRATEGY_AWARD_LIST_KEY = "big_market_strategy_award_list_key_"; + public static String STRATEGY_RATE_TABLE_KEY = "big_market_strategy_rate_table_key_"; + public static String STRATEGY_RATE_RANGE_KEY = "big_market_strategy_rate_range_key_"; + public static String RULE_TREE_VO_KEY = "rule_tree_vo_key_"; + public static String STRATEGY_AWARD_COUNT_KEY = "strategy_award_count_key_"; + public static String STRATEGY_AWARD_COUNT_QUERY_KEY = "strategy_award_count_query_key"; + public static String STRATEGY_RULE_WEIGHT_KEY = "strategy_rule_weight_key_"; + public static String ACTIVITY_SKU_COUNT_QUERY_KEY = "activity_sku_count_query_key"; + public static String ACTIVITY_SKU_STOCK_COUNT_KEY = "activity_sku_stock_count_key_"; + public static String ACTIVITY_SKU_COUNT_CLEAR_KEY = "activity_sku_count_clear_key_"; + public static String ACTIVITY_ACCOUNT_LOCK = "activity_account_lock_"; + public static String ACTIVITY_ACCOUNT_UPDATE_LOCK = "activity_account_update_lock_"; + public static String USER_CREDIT_ACCOUNT_LOCK = "user_credit_account_lock_"; + public static String STRATEGY_ARMORY_ALGORITHM_KEY = "strategy_armory_algorithm_key_"; + + } + }