├── .gitee
├── ISSUE_TEMPLATE.zh-CN.md
└── PULL_REQUEST_TEMPLATE.zh-CN.md
├── .gitignore
├── LICENSE
├── README.md
├── docker
├── app.Dockerfile
├── base.Dockerfile
├── docker-compose.kafka.yml
├── docker-compose.monolith.yml
├── docker-compose.postgres.yml
├── docker-compose.redis-cluster.yml
├── docker-compose.redis-sentinel.yml
├── docker-compose.redis-standalone.yml
├── kafka.env
├── protocol.Dockerfile
├── schema
│ └── schema-postgres.sql
└── start.sh
├── jcpp-app-bootstrap
├── pom.xml
└── src
│ ├── layers.xml
│ ├── main
│ ├── java
│ │ └── sanbing
│ │ │ └── jcpp
│ │ │ └── JCPPServerApplication.java
│ └── resources
│ │ ├── app-service.yml
│ │ ├── banner.txt
│ │ └── log4j2.xml
│ └── test
│ ├── java
│ └── sanbing
│ │ └── jcpp
│ │ ├── AbstractTestBase.java
│ │ ├── app
│ │ └── dal
│ │ │ └── mapper
│ │ │ ├── GunMapperIT.java
│ │ │ ├── OrderMapperIT.java
│ │ │ ├── PileMapperIT.java
│ │ │ ├── StationMapperIT.java
│ │ │ └── UserMapperIT.java
│ │ └── infrastructure
│ │ └── cache
│ │ └── RedisCacheConfigurationIT.java
│ └── resources
│ └── app-service-test.properties
├── jcpp-app
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── app
│ ├── adapter
│ └── TestController.java
│ ├── dal
│ ├── config
│ │ ├── DalConfig.java
│ │ └── ibatis
│ │ │ ├── enums
│ │ │ ├── GunOptStatusEnum.java
│ │ │ ├── GunRunStatusEnum.java
│ │ │ ├── OrderStatusEnum.java
│ │ │ ├── OrderTypeEnum.java
│ │ │ ├── OwnerTypeEnum.java
│ │ │ ├── PileStatusEnum.java
│ │ │ ├── PileTypeEnum.java
│ │ │ ├── StationStatusEnum.java
│ │ │ └── UserStatusEnum.java
│ │ │ └── typehandlers
│ │ │ ├── JsonbTypeHandler.java
│ │ │ └── UUIDTypeHandler.java
│ ├── entity
│ │ ├── Gun.java
│ │ ├── Order.java
│ │ ├── Pile.java
│ │ ├── Station.java
│ │ └── User.java
│ └── mapper
│ │ ├── GunMapper.java
│ │ ├── OrderMapper.java
│ │ ├── PileMapper.java
│ │ ├── StationMapper.java
│ │ └── UserMapper.java
│ ├── data
│ └── PileSession.java
│ ├── repository
│ ├── AbstractCachedEntityRepository.java
│ ├── AbstractEntityRepository.java
│ ├── CachedVersionedEntityRepository.java
│ ├── PileRepository.java
│ └── PileRepositoryImpl.java
│ └── service
│ ├── DownlinkCallService.java
│ ├── PileProtocolService.java
│ ├── cache
│ ├── pile
│ │ ├── PileCacheEvictEvent.java
│ │ ├── PileCacheKey.java
│ │ ├── PileCaffeineCache.java
│ │ └── PileRedisCache.java
│ └── session
│ │ ├── PileSessionCacheKey.java
│ │ ├── PileSessionCaffeineCache.java
│ │ └── PileSessionRedisCache.java
│ ├── config
│ └── DownlinkRestTemplateConfiguration.java
│ ├── grpc
│ └── DownlinkGrpcClient.java
│ ├── impl
│ ├── DefaultPileProtocolService.java
│ ├── GrpcDownlinkCallService.java
│ └── RestDownlinkCallService.java
│ └── queue
│ ├── AbstractConsumerService.java
│ ├── AppConsumerStats.java
│ ├── AppQueueConsumerManager.java
│ ├── QueueConsumerManagerTask.java
│ ├── QueueConsumerTask.java
│ ├── QueueEvent.java
│ └── consumer
│ └── ProtocolUplinkConsumerService.java
├── jcpp-infrastructure-cache
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── infrastructure
│ └── cache
│ ├── CacheConstants.java
│ ├── CacheSpecs.java
│ ├── CacheSpecsMap.java
│ ├── CacheTransaction.java
│ ├── CacheValueWrapper.java
│ ├── CaffeineCacheTransaction.java
│ ├── CaffeineTransactionalCache.java
│ ├── HasVersion.java
│ ├── JCPPCaffeineCacheConfiguration.java
│ ├── JCPPJCPPRedisClusterConfiguration.java
│ ├── JCPPJCPPRedisSentinelConfiguration.java
│ ├── JCPPJCPPRedisStandaloneConfiguration.java
│ ├── JCPPRedisCacheConfiguration.java
│ ├── JCPPRedisSerializer.java
│ ├── RedisCacheTransaction.java
│ ├── RedisTransactionalCache.java
│ ├── SimpleCacheValueWrapper.java
│ ├── TransactionalCache.java
│ ├── VersionedCache.java
│ ├── VersionedCacheKey.java
│ ├── VersionedCaffeineCache.java
│ └── VersionedRedisCache.java
├── jcpp-infrastructure-proto
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── sanbing
│ │ └── jcpp
│ │ └── infrastructure
│ │ └── proto
│ │ ├── ProtoConverter.java
│ │ └── model
│ │ └── PricingModel.java
│ └── proto
│ ├── cluster.proto
│ └── protocol.proto
├── jcpp-infrastructure-queue
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── infrastructure
│ └── queue
│ ├── AbstractQueueConsumerTemplate.java
│ ├── Callback.java
│ ├── DefaultQueueMsg.java
│ ├── DefaultQueueMsgHeaders.java
│ ├── KafkaQueueMsg.java
│ ├── PackCallback.java
│ ├── PackProcessingContext.java
│ ├── ProtoQueueMsg.java
│ ├── QueueAdmin.java
│ ├── QueueCallback.java
│ ├── QueueConsumer.java
│ ├── QueueMsg.java
│ ├── QueueMsgHeaders.java
│ ├── QueueMsgMetadata.java
│ ├── QueueProducer.java
│ ├── common
│ ├── QueueConfig.java
│ ├── QueueConstants.java
│ └── TopicPartitionInfo.java
│ ├── discovery
│ ├── DefaultServiceInfoProvider.java
│ ├── DiscoveryProvider.java
│ ├── DummyDiscoveryProvider.java
│ ├── HashPartitionProvider.java
│ ├── PartitionProvider.java
│ ├── QueueKey.java
│ ├── ServiceInfoProvider.java
│ ├── ServiceType.java
│ ├── ZkDiscoveryProvider.java
│ └── event
│ │ ├── JCPPApplicationEvent.java
│ │ ├── JCPPApplicationEventListener.java
│ │ ├── OtherServiceShutdownEvent.java
│ │ └── PartitionChangeEvent.java
│ ├── kafka
│ ├── KafkaAdmin.java
│ ├── KafkaConsumerStatisticConfig.java
│ ├── KafkaConsumerStatsService.java
│ ├── KafkaConsumerTemplate.java
│ ├── KafkaDecoder.java
│ ├── KafkaProducerTemplate.java
│ ├── KafkaQueueMsgMetadata.java
│ ├── KafkaSettings.java
│ └── KafkaTopicConfigs.java
│ ├── memory
│ ├── DefaultInMemoryStorage.java
│ ├── InMemoryQueueConsumer.java
│ ├── InMemoryQueueProducer.java
│ └── InMemoryStorage.java
│ ├── processing
│ └── IdMsgPair.java
│ ├── provider
│ ├── AppQueueFactory.java
│ ├── InMemoryAppQueueFactory.java
│ └── KafkaAppQueueFactory.java
│ └── settings
│ └── QueueAppSettings.java
├── jcpp-infrastructure-stats
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── infrastructure
│ └── stats
│ ├── DefaultCounter.java
│ ├── DefaultMessagesStats.java
│ ├── DefaultStatsFactory.java
│ ├── MessagesStats.java
│ ├── StatsCounter.java
│ ├── StatsFactory.java
│ └── StatsTimer.java
├── jcpp-infrastructure-util
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── sanbing
│ │ └── jcpp
│ │ └── infrastructure
│ │ └── util
│ │ ├── JCPPHashUtil.java
│ │ ├── JCPPPair.java
│ │ ├── SystemUtil.java
│ │ ├── annotation
│ │ ├── AfterStartUp.java
│ │ ├── AppComponent.java
│ │ └── ProtocolComponent.java
│ │ ├── async
│ │ ├── JCPPAsynchron.java
│ │ ├── JCPPExecutors.java
│ │ ├── JCPPForkJoinWorkerThreadFactory.java
│ │ ├── JCPPThreadFactory.java
│ │ └── JCPPVirtualThreadFactory.java
│ │ ├── codec
│ │ ├── BCDUtil.java
│ │ ├── ByteUtil.java
│ │ └── CP56Time2aUtil.java
│ │ ├── config
│ │ ├── ConstraintValidator.java
│ │ ├── ScheduledTaskConfig.java
│ │ ├── ShardingThreadPool.java
│ │ └── ThreadPoolConfiguration.java
│ │ ├── exception
│ │ ├── DataValidationException.java
│ │ ├── DownlinkException.java
│ │ └── IncorrectParameterException.java
│ │ ├── jackson
│ │ ├── BigNumberSerializer.java
│ │ ├── DataTypeModule.java
│ │ ├── DateDeserializer.java
│ │ ├── DateSerializer.java
│ │ ├── InstantDeserializer.java
│ │ ├── InstantSerializer.java
│ │ ├── JacksonUtil.java
│ │ ├── LocalDateTimeDeserializer.java
│ │ ├── LocalDateTimeSerializer.java
│ │ ├── LocalTimeDeserializer.java
│ │ ├── LocalTimeSerializer.java
│ │ ├── LongTimestampDeserializer.java
│ │ ├── SqlDateDeserializer.java
│ │ ├── SqlDateSerializer.java
│ │ ├── TimestampDeserializer.java
│ │ └── TimestampSerializer.java
│ │ ├── mdc
│ │ └── MDCUtils.java
│ │ ├── property
│ │ ├── JCPPProperty.java
│ │ └── PropertyUtils.java
│ │ ├── trace
│ │ ├── TraceIdGenerator.java
│ │ ├── Tracer.java
│ │ ├── TracerCallable.java
│ │ ├── TracerContextUtil.java
│ │ └── TracerRunnable.java
│ │ └── validation
│ │ ├── Length.java
│ │ ├── StringLengthValidator.java
│ │ └── Validator.java
│ └── test
│ └── java
│ └── sanbing
│ └── jcpp
│ └── infrastructure
│ └── util
│ ├── async
│ └── JCPPExecutorsTest.java
│ └── codec
│ ├── BCDUtilTest.java
│ └── CP56Time2aUtilTest.java
├── jcpp-protocol-api
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── protocol
│ ├── ProtocolBootstrap.java
│ ├── ProtocolContext.java
│ ├── ProtocolMessageProcessor.java
│ ├── adapter
│ ├── DownlinkController.java
│ ├── DownlinkGrpcService.java
│ └── config
│ │ ├── TracerInterceptor.java
│ │ ├── UndertowServletWebServerCustomizer.java
│ │ └── WebMvcConfiguration.java
│ ├── cfg
│ ├── ForwarderCfg.java
│ ├── KafkaCfg.java
│ ├── ListenerCfg.java
│ ├── MemoryCfg.java
│ ├── ProtocolCfg.java
│ ├── TcpCfg.java
│ ├── TcpHandlerCfg.java
│ └── enums
│ │ ├── ForwarderType.java
│ │ └── TcpHandlerType.java
│ ├── domain
│ ├── DownlinkCmdEnum.java
│ ├── ListenerToHandlerMsg.java
│ ├── ProtocolSession.java
│ ├── ProtocolUplinkMsg.java
│ ├── SessionCloseReason.java
│ └── SessionToHandlerMsg.java
│ ├── forwarder
│ ├── Forwarder.java
│ ├── KafkaForwarder.java
│ └── MemoryForwarder.java
│ ├── listener
│ ├── ChannelHandlerInitializer.java
│ ├── ChannelHandlerParameter.java
│ ├── Listener.java
│ └── tcp
│ │ ├── TcpChannelHandler.java
│ │ ├── TcpListener.java
│ │ ├── TcpSession.java
│ │ ├── configs
│ │ ├── BinaryHandlerConfiguration.java
│ │ ├── HandlerConfiguration.java
│ │ ├── JsonHandlerConfiguration.java
│ │ └── TextHandlerConfiguration.java
│ │ ├── decoder
│ │ ├── JCPPHeadTailFrameDecoder.java
│ │ ├── JCPPLengthFieldBasedFrameDecoder.java
│ │ └── TcpMsgDecoder.java
│ │ ├── enums
│ │ ├── ReadAct.java
│ │ └── SequenceNumberLength.java
│ │ └── handler
│ │ ├── ConnectionLimitHandler.java
│ │ ├── IdleEventHandler.java
│ │ └── TracerHandler.java
│ └── provider
│ ├── ProtocolSessionRegistryProvider.java
│ ├── ProtocolsConfigProvider.java
│ └── impl
│ ├── DefaultProtocolSessionRegistryProvider.java
│ └── DefaultProtocolsConfigProvider.java
├── jcpp-protocol-bootstrap
├── pom.xml
└── src
│ ├── layers.xml
│ ├── main
│ ├── java
│ │ └── sanbing
│ │ │ └── jcpp
│ │ │ └── protocol
│ │ │ └── JCPPProtocolServiceApplication.java
│ └── resources
│ │ ├── banner.txt
│ │ ├── log4j2.xml
│ │ └── protocol-service.yml
│ └── test
│ └── java
│ └── sanbing
│ └── jcpp
│ └── protocol
│ ├── AbstractProtocolTestBase.java
│ └── adapter
│ └── DownlinkControllerIT.java
├── jcpp-protocol-yunkuaichong
├── READMD.md
├── pom.xml
└── src
│ └── main
│ └── java
│ └── sanbing
│ └── jcpp
│ └── protocol
│ └── yunkuaichong
│ ├── AbstractYunKuaiChongCmdExe.java
│ ├── YunKuaiChongDownlinkCmdExe.java
│ ├── YunKuaiChongDwonlinkMessage.java
│ ├── YunKuaiChongProtocolMessageProcessor.java
│ ├── YunKuaiChongUplinkCmdExe.java
│ ├── YunKuaiChongUplinkMessage.java
│ ├── annotation
│ └── YunKuaiChongCmd.java
│ ├── enums
│ └── YunKuaiChongDownlinkCmdEnum.java
│ ├── v150
│ ├── YunkuaichongV150ProtocolBootstrap.java
│ └── cmd
│ │ ├── YunKuaiChongV150BmsHandshakeULCmd.java
│ │ ├── YunKuaiChongV150HeartbeatULCmd.java
│ │ ├── YunKuaiChongV150LoginAckDLCmd.java
│ │ ├── YunKuaiChongV150LoginULCmd.java
│ │ ├── YunKuaiChongV150QueryPricingModelAckDLCmd.java
│ │ ├── YunKuaiChongV150QueryPricingModelULCmd.java
│ │ ├── YunKuaiChongV150RealTimeDataULCmd.java
│ │ ├── YunKuaiChongV150RemoteStartDLCmd.java
│ │ ├── YunKuaiChongV150RemoteStartResultULCmd.java
│ │ ├── YunKuaiChongV150RemoteStopDLCmd.java
│ │ ├── YunKuaiChongV150RemoteStopResultULCmd.java
│ │ ├── YunKuaiChongV150SetPricingModelAckULCmd.java
│ │ ├── YunKuaiChongV150SetPricingModelDLCmd.java
│ │ ├── YunKuaiChongV150TransactionRecordAckDLCmd.java
│ │ ├── YunKuaiChongV150TransactionRecordULCmd.java
│ │ ├── YunKuaiChongV150VerifyPricingModelAckDLCmd.java
│ │ └── YunKuaiChongV150VerifyPricingModelULCmd.java
│ └── v160
│ ├── YunkuaichongV160ProtocolBootstrap.java
│ └── cmd
│ ├── YunKuaiChongV160RemoteParallelStartDLCmd.java
│ └── YunKuaiChongV160RemoteParallelStartResultULCmd.java
├── jcpp-testing
└── pom.xml
├── license-header-template.txt
└── pom.xml
/.gitee/ISSUE_TEMPLATE.zh-CN.md:
--------------------------------------------------------------------------------
1 | ### 该问题是怎么引起的?
2 |
3 |
4 |
5 | ### 重现步骤
6 |
7 |
8 |
9 | ### 报错信息
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md:
--------------------------------------------------------------------------------
1 | ### 相关的Issue
2 |
3 |
4 | ### 原因(目的、解决的问题等)
5 |
6 |
7 | ### 描述(做了什么,变更了什么)
8 |
9 |
10 | ### 测试用例(新增、改动、可能影响的功能)
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 | HELP.md
4 | target/
5 | !.mvn/wrapper/maven-wrapper.jar
6 | !**/src/main/**/target/
7 | !**/src/test/**/target/
8 |
9 | # Log file
10 | *.log
11 |
12 | # BlueJ files
13 | *.ctxt
14 |
15 | # Mobile Tools for Java (J2ME)
16 | .mtj.tmp/
17 |
18 | # Package Files #
19 | *.jar
20 | *.war
21 | *.nar
22 | *.ear
23 | *.zip
24 | *.tar.gz
25 | *.rar
26 |
27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
28 | hs_err_pid*
29 |
30 | ### STS ###
31 | .apt_generated
32 | .classpath
33 | .factorypath
34 | .project
35 | .settings
36 | .springBeans
37 | .sts4-cache
38 |
39 | ### IntelliJ IDEA ###
40 | .idea
41 | *.iws
42 | *.iml
43 | *.ipr
44 |
45 | ### NetBeans ###
46 | /nbproject/private/
47 | /nbbuild/
48 | /dist/
49 | /nbdist/
50 | /.nb-gradle/
51 | build/
52 | !**/src/main/**/build/
53 | !**/src/test/**/build/
54 |
55 | ### VS Code ###
56 | .vscode/
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JChargePointProtocol
2 |
3 | ###### 一个高性能、分布式、支持海量并发量的充电桩JAVA服务端,计划支持100种协议,为充电应用提供基础能力。
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | ------------------------------
17 | #### 当前支持的充电桩协议
18 | | 协议名 | 版本号 |
19 | |---|------------|
20 | | 云快充 | 1.5.0、1.6.0 |
21 |
22 | ------------------------------
23 | #### 充电桩协议文档
24 | 百度网盘: https://pan.baidu.com/s/1xT8xWty1XRUHDzTZM_8aLw?pwd=jcpp
25 |
26 | ------------------------------
27 |
28 | ##### 文档请到联系作者加入社群
29 |
30 |
31 | ------------------------------
32 | #### 参与贡献
33 |
34 | 1. Fork 本仓库
35 | 2. 新建 Feat_xxx 分支
36 | 3. 提交代码
37 | 4. 加入社群
38 | 5. 新建 Pull Request
39 |
40 | #### 版权
41 | 开源部分,仅供学习和交流研究使用
42 |
43 |
--------------------------------------------------------------------------------
/docker/app.Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/jcpp-base:1.0 AS base
10 | WORKDIR /app
11 | COPY . .
12 | RUN mvn -U -B -T 0.8C clean install -DskipTests
13 |
14 | #分层
15 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye AS builder
16 | WORKDIR /app
17 | COPY --from=base /app/jcpp-app-bootstrap/target/application.jar application.jar
18 | RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
19 |
20 | # 执行
21 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye
22 | RUN useradd -m sanbing
23 | WORKDIR /home/sanbing
24 |
25 | COPY --from=builder /app/extracted/dependencies/ ./
26 | COPY --from=builder /app/extracted/spring-boot-loader/ ./
27 | COPY --from=builder /app/extracted/snapshot-dependencies/ ./
28 | COPY --from=builder /app/extracted/application/ ./
29 | COPY --from=base /app/jcpp-app-bootstrap/target/conf ./config
30 | COPY --from=base /app/docker/start.sh .
31 |
32 | RUN chmod a+x start.sh \
33 | && mkdir -p /home/sanbing/logs/jcpp \
34 | && mkdir -p /home/sanbing/logs/accesslog \
35 | && mkdir -p /home/sanbing/logs/gc \
36 | && mkdir -p /home/sanbing/logs/heapdump \
37 | && chmod 700 -R /home/sanbing/logs/* \
38 | && chown -R sanbing:sanbing /home/sanbing
39 |
40 | EXPOSE 8080 8080
41 |
42 | ENV APP_LOG_LEVEL=INFO
43 | ENV PROTOCOLS_LOG_LEVEL=INFO
44 |
45 | USER sanbing
46 | CMD ["/bin/bash", "start.sh"]
47 |
--------------------------------------------------------------------------------
/docker/base.Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/mvn:3.9.9-jdk21 AS base
10 | WORKDIR /app
11 | COPY . .
12 | RUN mvn -U -B -T 0.8C clean install -DskipTests \
13 | && rm -rf /app
14 |
15 |
--------------------------------------------------------------------------------
/docker/docker-compose.kafka.yml:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | networks:
10 | sanbing-network:
11 | driver: bridge
12 | name: sanbing-network
13 | ipam:
14 | config:
15 | - subnet: 10.10.0.0/24
16 |
17 | services:
18 | zookeeper:
19 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/zookeeper:3.9
20 | restart: always
21 | networks:
22 | - sanbing-network
23 | ports:
24 | - "2181:2181"
25 | environment:
26 | ALLOW_ANONYMOUS_LOGIN: true
27 | kafka:
28 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/kafka:3.7.1
29 | restart: always
30 | depends_on:
31 | - zookeeper
32 | networks:
33 | - sanbing-network
34 | ports:
35 | - "9092:9092"
36 | env_file:
37 | - kafka.env
38 | kafka-exporter:
39 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/kafka-exporter:latest
40 | restart: always
41 | depends_on:
42 | - kafka
43 | networks:
44 | - sanbing-network
45 | ports:
46 | - "9308:9308"
47 | command:
48 | - '--kafka.server=kafka:9092'
49 |
--------------------------------------------------------------------------------
/docker/docker-compose.monolith.yml:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | networks:
10 | sanbing-network:
11 | driver: bridge
12 | name: sanbing-network
13 | ipam:
14 | config:
15 | - subnet: 10.10.0.0/24
16 |
17 | services:
18 | jcpp-node-0:
19 | restart: always
20 | build:
21 | context: ..
22 | dockerfile: docker/app.Dockerfile
23 | networks:
24 | - sanbing-network
25 | ports:
26 | - "8080:8080"
27 | - "38001:38001"
28 | environment:
29 | HTTP_BIND_PORT: 8080
--------------------------------------------------------------------------------
/docker/docker-compose.postgres.yml:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | volumes:
10 | postgresql_data: {}
11 |
12 | networks:
13 | sanbing-network:
14 | driver: bridge
15 | name: sanbing-network
16 | ipam:
17 | config:
18 | - subnet: 10.10.0.0/24
19 |
20 | services:
21 | postgres:
22 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/postgresql:17
23 | restart: always
24 | networks:
25 | - sanbing-network
26 | ports:
27 | - "5432:5432"
28 | environment:
29 | - 'POSTGRES_DB=jcpp'
30 | - 'POSTGRES_PASSWORD=postgres'
31 | - 'POSTGRESQL_MAX_CONNECTIONS=1000'
32 | - 'POSTGRESQL_DEFAULT_TRANSACTION_ISOLATION=read committed'
33 | - 'TZ=Asia/Shanghai'
34 | volumes:
35 | - postgresql_data:/bitnami/postgresql
36 | - ./schema/schema-postgres.sql:/docker-entrypoint-initdb.d/init.sql
--------------------------------------------------------------------------------
/docker/docker-compose.redis-sentinel.yml:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | networks:
10 | sanbing-network:
11 | driver: bridge
12 | name: sanbing-network
13 | ipam:
14 | config:
15 | - subnet: 10.10.0.0/24
16 |
17 | services:
18 | redis-master:
19 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/redis:7.4
20 | restart: always
21 | networks:
22 | - sanbing-network
23 | environment:
24 | - 'REDIS_REPLICATION_MODE=master'
25 | - 'REDIS_PASSWORD=sanbing'
26 |
27 | redis-slave:
28 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/redis:7.4
29 | restart: always
30 | networks:
31 | - sanbing-network
32 | environment:
33 | - 'REDIS_REPLICATION_MODE=slave'
34 | - 'REDIS_MASTER_HOST=redis-master'
35 | - 'REDIS_MASTER_PASSWORD=sanbing'
36 | - 'REDIS_PASSWORD=sanbing'
37 | depends_on:
38 | - redis-master
39 |
40 | redis-sentinel:
41 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/redis-sentinel:7.4
42 | restart: always
43 | networks:
44 | - sanbing-network
45 | environment:
46 | - 'REDIS_MASTER_HOST=redis-master'
47 | - 'REDIS_MASTER_SET=mymaster'
48 | - 'REDIS_SENTINEL_PASSWORD=sanbing'
49 | - 'REDIS_MASTER_PASSWORD=sanbing'
50 | depends_on:
51 | - redis-master
52 | - redis-slave
53 |
--------------------------------------------------------------------------------
/docker/docker-compose.redis-standalone.yml:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | networks:
10 | sanbing-network:
11 | driver: bridge
12 | name: sanbing-network
13 | ipam:
14 | config:
15 | - subnet: 10.10.0.0/24
16 |
17 | services:
18 | redis:
19 | image: registry.cn-hangzhou.aliyuncs.com/sanbing/redis:7.4
20 | restart: always
21 | networks:
22 | - sanbing-network
23 | ports:
24 | - '6379:6379'
25 | environment:
26 | - 'REDIS_PASSWORD=sanbing'
27 |
--------------------------------------------------------------------------------
/docker/kafka.env:
--------------------------------------------------------------------------------
1 | KAFKA_CFG_NODE_ID=0
2 | ALLOW_PLAINTEXT_LISTENER=yes
3 | KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
4 | KAFKA_CFG_LISTENERS=INSIDE://:9093,OUTSIDE://:9092
5 | KAFKA_CFG_ADVERTISED_LISTENERS=INSIDE://:9093,OUTSIDE://kafka:9092
6 | KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
7 | KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
8 | KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INSIDE
9 | KAFKA_CFG_LOG_RETENTION_BYTES=1073741824
10 | KAFKA_CFG_SEGMENT_BYTES=268435456
11 | KAFKA_CFG_LOG_RETENTION_MS=300000
12 | KAFKA_CFG_LOG_CLEANUP_POLICY=delete
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docker/protocol.Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | # 微信:mohan_88888
4 | # 抖音:程序员三丙
5 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | #
7 |
8 |
9 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/jcpp-base:1.0 AS base
10 | WORKDIR /app
11 | COPY . .
12 | RUN mvn -U -B -T 0.8C clean install -DskipTests
13 |
14 | #分层
15 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye AS builder
16 | WORKDIR /app
17 | COPY --from=base /app/jcpp-protocol-bootstrap/target/application.jar application.jar
18 | RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
19 |
20 | # 执行
21 | FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye
22 | RUN useradd -m sanbing
23 | WORKDIR /home/sanbing
24 |
25 | COPY --from=builder /app/extracted/dependencies/ ./
26 | COPY --from=builder /app/extracted/spring-boot-loader/ ./
27 | COPY --from=builder /app/extracted/snapshot-dependencies/ ./
28 | COPY --from=builder /app/extracted/application/ ./
29 | COPY --from=base /app/jcpp-app-bootstrap/target/conf ./config
30 | COPY --from=base /app/docker/start.sh .
31 |
32 | RUN chmod a+x start.sh \
33 | && mkdir -p /home/sanbing/logs/jcpp \
34 | && mkdir -p /home/sanbing/logs/accesslog \
35 | && mkdir -p /home/sanbing/logs/gc \
36 | && mkdir -p /home/sanbing/logs/heapdump \
37 | && chmod 700 -R /home/sanbing/logs/* \
38 | && chown -R sanbing:sanbing /home/sanbing
39 |
40 | EXPOSE 8080 8080
41 |
42 | ENV PROTOCOLS_LOG_LEVEL=INFO
43 |
44 | USER sanbing
45 | CMD ["/bin/bash", "start.sh"]
46 |
47 |
--------------------------------------------------------------------------------
/docker/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # 开源代码,仅供学习和交流研究使用,商用请联系三丙
4 | # 微信:mohan_88888
5 | # 抖音:程序员三丙
6 | # 付费课程知识星球:https://t.zsxq.com/aKtXo
7 | #
8 |
9 |
10 | echo "Starting Server ..."
11 |
12 | export JAVA_APP_OPTS="-XX:+UseContainerSupport -XX:InitialRAMPercentage=50 -XX:MaxRAMPercentage=90 \
13 | -Xlog:gc*,heap*,age*,safepoint=debug:file=/home/sanbing/logs/gc/gc.log:time,uptime,level,tags:filecount=10,filesize=10M \
14 | -XX:+HeapDumpOnOutOfMemoryError \
15 | -XX:HeapDumpPath=/home/sanbing/logs/heapdump/ \
16 | -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark \
17 | -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10 \
18 | -Xss512k -XX:G1ReservePercent=20 \
19 | -XX:-OmitStackTraceInFastThrow \
20 | -Dlogging.config=/home/sanbing/config/log4j2.xml"
21 |
22 | #export JAVA_OPTS_EXTEND="-Xdebug -Xrunjdwp:transport=dt_socket,address=0.0.0.0:8000,server=y,suspend=n"
23 |
24 | exec java $JAVA_APP_OPTS $JAVA_OPTS_EXTEND $JAVA_OPTS -Dnetworkaddress.cache.ttl=60 -jar application.jar
25 |
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/layers.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
15 |
16 | org/springframework/boot/loader/**
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | *:*:*SNAPSHOT
26 |
27 |
28 |
29 |
30 | dependencies
31 | spring-boot-loader
32 | snapshot-dependencies
33 | application
34 |
35 |
36 |
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/main/java/sanbing/jcpp/JCPPServerApplication.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp;
8 |
9 | import org.springframework.boot.Banner;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.boot.builder.SpringApplicationBuilder;
12 | import org.springframework.scheduling.annotation.EnableAsync;
13 | import org.springframework.scheduling.annotation.EnableScheduling;
14 |
15 | import java.util.Arrays;
16 |
17 | /**
18 | * @author baigod
19 | */
20 | @SpringBootApplication
21 | @EnableAsync
22 | @EnableScheduling
23 | public class JCPPServerApplication {
24 |
25 | private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name";
26 | private static final String DEFAULT_SPRING_CONFIG_PARAM = SPRING_CONFIG_NAME_KEY + "=" + "app-service";
27 |
28 | public static void main(String[] args) {
29 | new SpringApplicationBuilder(JCPPServerApplication.class).bannerMode(Banner.Mode.LOG).run(updateArguments(args));
30 | }
31 |
32 | private static String[] updateArguments(String[] args) {
33 | if (Arrays.stream(args).noneMatch(arg -> arg.startsWith(SPRING_CONFIG_NAME_KEY))) {
34 | String[] modifiedArgs = new String[args.length + 1];
35 | System.arraycopy(args, 0, modifiedArgs, 0, args.length);
36 | modifiedArgs[args.length] = DEFAULT_SPRING_CONFIG_PARAM;
37 | return modifiedArgs;
38 | }
39 | return args;
40 | }
41 | }
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 |
2 | ___ ________ ________ ________
3 | |\ \|\ ____\|\ __ \|\ __ \
4 | \ \ \ \ \___|\ \ \|\ \ \ \|\ \
5 | __ \ \ \ \ \ \ \ ____\ \ ____\
6 | |\ \\_\ \ \ \____\ \ \___|\ \ \___|
7 | \ \________\ \_______\ \__\ \ \__\
8 | \|________|\|_______|\|__| \|__|
9 |
10 | ===================================================
11 | :: ${application.title} :: ${application.formatted-version}
12 | ===================================================
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/test/java/sanbing/jcpp/AbstractTestBase.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp;
8 |
9 | import org.junit.jupiter.api.MethodOrderer;
10 | import org.junit.jupiter.api.TestMethodOrder;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.boot.test.context.SpringBootTest;
14 | import org.springframework.test.context.ActiveProfiles;
15 |
16 | /**
17 | * @author baigod
18 | */
19 | @ActiveProfiles("test")
20 | @SpringBootTest(classes = JCPPServerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
21 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
22 | public class AbstractTestBase {
23 |
24 | static {
25 | System.setProperty("spring.config.name", "app-service");
26 | }
27 |
28 | protected final Logger log = LoggerFactory.getLogger(this.getClass());
29 | }
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/test/java/sanbing/jcpp/app/dal/mapper/StationMapperIT.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.toolkit.Wrappers;
10 | import jakarta.annotation.Resource;
11 | import org.junit.jupiter.api.Test;
12 | import sanbing.jcpp.AbstractTestBase;
13 | import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
14 | import sanbing.jcpp.app.dal.config.ibatis.enums.StationStatusEnum;
15 | import sanbing.jcpp.app.dal.entity.Station;
16 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
17 |
18 | import java.time.LocalDateTime;
19 | import java.util.UUID;
20 |
21 | import static sanbing.jcpp.app.dal.mapper.UserMapperIT.NORMAL_USER_ID;
22 |
23 | /**
24 | * @author baigod
25 | */
26 | class StationMapperIT extends AbstractTestBase {
27 | static final UUID NORMAL_STATION_ID = UUID.fromString("07d80c81-fe99-4a1f-a6aa-dc4d798b5626");
28 |
29 | @Resource
30 | StationMapper stationMapper;
31 |
32 | @Test
33 | void curdTest() {
34 | stationMapper.delete(Wrappers.lambdaQuery());
35 |
36 | Station station = Station.builder()
37 | .id(NORMAL_STATION_ID)
38 | .createdTime(LocalDateTime.now())
39 | .additionalInfo(JacksonUtil.newObjectNode())
40 | .stationName("三丙家专属充电站")
41 | .stationCode("S20241001001")
42 | .ownerId(NORMAL_USER_ID)
43 | .longitude(120.107936F)
44 | .latitude(30.267014F)
45 | .ownerType(OwnerTypeEnum.C)
46 | .province("浙江省")
47 | .city("杭州市")
48 | .county("西湖区")
49 | .address("西溪路552-1号")
50 | .status(StationStatusEnum.OPERATIONAL)
51 | .build();
52 |
53 | stationMapper.insertOrUpdate(station);
54 |
55 | log.info("{}", stationMapper.selectById(NORMAL_STATION_ID));
56 | }
57 | }
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/test/java/sanbing/jcpp/app/dal/mapper/UserMapperIT.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.toolkit.Wrappers;
10 | import jakarta.annotation.Resource;
11 | import org.junit.jupiter.api.Test;
12 | import sanbing.jcpp.AbstractTestBase;
13 | import sanbing.jcpp.app.dal.config.ibatis.enums.UserStatusEnum;
14 | import sanbing.jcpp.app.dal.entity.User;
15 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
16 |
17 | import java.time.LocalDateTime;
18 | import java.util.UUID;
19 |
20 | /**
21 | * @author baigod
22 | */
23 | class UserMapperIT extends AbstractTestBase {
24 | static final UUID NORMAL_USER_ID = UUID.fromString("21cbf909-a23a-4396-840a-f34061f59f95");
25 |
26 | @Resource
27 | private UserMapper userMapper;
28 |
29 | @Test
30 | void curdTest() {
31 | userMapper.delete(Wrappers.lambdaQuery());
32 |
33 | User user = User.builder()
34 | .id(NORMAL_USER_ID)
35 | .createdTime(LocalDateTime.now())
36 | .additionalInfo(JacksonUtil.newObjectNode())
37 | .status(UserStatusEnum.ENABLE)
38 | .userName("sanbing")
39 | .userCredentials(JacksonUtil.newObjectNode())
40 | .build();
41 |
42 | userMapper.insertOrUpdate(user);
43 |
44 | log.info("{}", userMapper.selectById(NORMAL_USER_ID));
45 | }
46 | }
--------------------------------------------------------------------------------
/jcpp-app-bootstrap/src/test/resources/app-service-test.properties:
--------------------------------------------------------------------------------
1 | service.protocols.yunkuaichongV150.listener.tcp.bind-port=0
2 | service.protocols.yunkuaichongV160.listener.tcp.bind-port=0
3 | service.protocol.rpc.port=0
--------------------------------------------------------------------------------
/jcpp-app/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
13 |
14 | sanbing
15 | jcpp-parent
16 | 1.0.0-SNAPSHOT
17 | ../pom.xml
18 |
19 | 4.0.0
20 |
21 | jcpp-app
22 | jar
23 | JChargePointProtocol App Module
24 | 应用模块
25 |
26 |
27 | ${basedir}/..
28 |
29 |
30 |
31 |
32 | sanbing
33 | jcpp-protocol-api
34 |
35 |
36 | sanbing
37 | jcpp-infrastructure-queue
38 |
39 |
40 | sanbing
41 | jcpp-infrastructure-cache
42 |
43 |
44 | org.postgresql
45 | postgresql
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-starter-jdbc
50 |
51 |
52 | com.baomidou
53 | mybatis-plus-spring-boot3-starter
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/GunOptStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum GunOptStatusEnum implements IEnum {
15 | AVAILABLE, // 可用状态
16 | IN_MAINTENANCE, // 维护中状态
17 | OUT_OF_SERVICE, // 停用状态
18 | RESERVED; // 已预约状态
19 |
20 | @Override
21 | public String getValue() {
22 | return name();
23 | }
24 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/GunRunStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum GunRunStatusEnum implements IEnum {
15 | IDLE, // 空闲
16 | INSERTED, // 已插枪
17 | CHARGING, // 充电中
18 | CHARGE_COMPLETE, // 充电完成
19 | DISCHARGE_READY, // 放电准备
20 | DISCHARGING, // 放电中
21 | DISCHARGE_COMPLETE, // 放电完成
22 | RESERVED, // 预约
23 | FAULT; // 故障
24 |
25 | @Override
26 | public String getValue() {
27 | return name();
28 | }
29 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/OrderStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | public enum OrderStatusEnum implements IEnum {
12 | PENDING,
13 | IN_CHARGING,
14 | COMPLETED,
15 | CANCELLED,
16 | TERMINATED,
17 | FAILED,
18 | REFUNDED;
19 |
20 |
21 | @Override
22 | public String getValue() {
23 | return name();
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/OrderTypeEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum OrderTypeEnum implements IEnum {
15 | CHARGE,
16 |
17 | DISCHARGE;
18 |
19 | @Override
20 | public String getValue() {
21 | return name();
22 | }
23 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/OwnerTypeEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum OwnerTypeEnum implements IEnum {
15 | C,
16 | B,
17 | G;
18 |
19 | @Override
20 | public String getValue() {
21 | return name();
22 | }
23 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum PileStatusEnum implements IEnum {
15 | IDLE, // 空闲
16 | WORKING, // 工作中
17 | FAULT, // 故障
18 | MAINTENANCE, // 维护中
19 | OFFLINE, // 离线
20 | ;
21 |
22 | @Override
23 | public String getValue() {
24 | return name();
25 | }
26 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileTypeEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum PileTypeEnum implements IEnum {
15 | AC, // 交流充电桩
16 | DC, // 直流充电桩
17 | ;
18 |
19 | @Override
20 | public String getValue() {
21 | return name();
22 | }
23 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/StationStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum StationStatusEnum implements IEnum {
15 | OPERATIONAL, // 正常运营
16 | PARTIAL_FAILURE, // 部分故障
17 | FULLY_LOADED, // 满载
18 | MAINTENANCE, // 维护中
19 | CLOSED, // 关闭
20 | WAITING_FOR_OPEN; // 待开放
21 |
22 | @Override
23 | public String getValue() {
24 | return name();
25 | }
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/UserStatusEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.enums;
8 |
9 | import com.baomidou.mybatisplus.annotation.IEnum;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public enum UserStatusEnum implements IEnum {
15 | ENABLE,
16 | DISABLE;
17 |
18 | @Override
19 | public String getValue() {
20 | return name();
21 | }
22 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/typehandlers/JsonbTypeHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.typehandlers;
8 |
9 | import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
10 | import com.fasterxml.jackson.databind.JsonNode;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.apache.ibatis.type.JdbcType;
13 | import org.apache.ibatis.type.MappedTypes;
14 | import org.postgresql.util.PGobject;
15 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
16 |
17 | import java.lang.reflect.Field;
18 | import java.sql.PreparedStatement;
19 | import java.sql.SQLException;
20 |
21 | @Slf4j
22 | @MappedTypes({JsonNode.class})
23 | public class JsonbTypeHandler extends JacksonTypeHandler {
24 |
25 | public JsonbTypeHandler(Class> type) {
26 | super(type);
27 | }
28 |
29 | public JsonbTypeHandler(Class> type, Field field) {
30 | super(type, field);
31 | }
32 |
33 | @Override
34 | public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
35 | if (ps != null) {
36 | PGobject jsonObject = new PGobject();
37 | jsonObject.setType("jsonb");
38 | jsonObject.setValue(JacksonUtil.toString(parameter));
39 | ps.setObject(i, jsonObject);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/typehandlers/UUIDTypeHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.config.ibatis.typehandlers;
8 |
9 | import org.apache.ibatis.type.BaseTypeHandler;
10 | import org.apache.ibatis.type.JdbcType;
11 |
12 | import java.sql.CallableStatement;
13 | import java.sql.PreparedStatement;
14 | import java.sql.ResultSet;
15 | import java.sql.SQLException;
16 | import java.util.UUID;
17 |
18 | /**
19 | * mysql UUID 类型转 varchar
20 | */
21 | public class UUIDTypeHandler extends BaseTypeHandler {
22 |
23 | @Override
24 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
25 | ps.setObject(i, parameter);
26 | }
27 |
28 | @Override
29 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
30 | return rs.getObject(columnName, UUID.class);
31 | }
32 |
33 | @Override
34 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
35 | return rs.getObject(columnIndex, UUID.class);
36 | }
37 |
38 | @Override
39 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
40 | return cs.getObject(columnIndex, UUID.class);
41 | }
42 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Gun.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.entity;
8 |
9 | import com.baomidou.mybatisplus.annotation.IdType;
10 | import com.baomidou.mybatisplus.annotation.TableId;
11 | import com.baomidou.mybatisplus.annotation.TableName;
12 | import com.fasterxml.jackson.databind.JsonNode;
13 | import lombok.AllArgsConstructor;
14 | import lombok.Builder;
15 | import lombok.Data;
16 | import lombok.NoArgsConstructor;
17 | import sanbing.jcpp.app.dal.config.ibatis.enums.GunOptStatusEnum;
18 | import sanbing.jcpp.app.dal.config.ibatis.enums.GunRunStatusEnum;
19 | import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
20 | import sanbing.jcpp.infrastructure.cache.HasVersion;
21 |
22 | import java.io.Serializable;
23 | import java.time.LocalDateTime;
24 | import java.util.UUID;
25 |
26 |
27 | @Data
28 | @TableName("jcpp_gun")
29 | @Builder
30 | @AllArgsConstructor
31 | @NoArgsConstructor
32 | public class Gun implements Serializable, HasVersion {
33 |
34 | @TableId(type = IdType.INPUT)
35 | private UUID id;
36 |
37 | private LocalDateTime createdTime;
38 |
39 | private JsonNode additionalInfo;
40 |
41 | private String gunNo;
42 |
43 | private String gunName;
44 |
45 | private String gunCode;
46 |
47 | private UUID stationId;
48 |
49 | private UUID pileId;
50 |
51 | private UUID ownerId;
52 |
53 | private OwnerTypeEnum ownerType;
54 |
55 | private GunRunStatusEnum runStatus;
56 |
57 | private LocalDateTime runStatusUpdatedTime;
58 |
59 | private GunOptStatusEnum optStatus;
60 |
61 | private Integer version;
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Order.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.entity;
8 |
9 | import com.baomidou.mybatisplus.annotation.IdType;
10 | import com.baomidou.mybatisplus.annotation.TableId;
11 | import com.baomidou.mybatisplus.annotation.TableName;
12 | import com.fasterxml.jackson.databind.JsonNode;
13 | import lombok.AllArgsConstructor;
14 | import lombok.Builder;
15 | import lombok.Data;
16 | import lombok.NoArgsConstructor;
17 | import sanbing.jcpp.app.dal.config.ibatis.enums.OrderStatusEnum;
18 | import sanbing.jcpp.app.dal.config.ibatis.enums.OrderTypeEnum;
19 |
20 | import java.io.Serializable;
21 | import java.math.BigDecimal;
22 | import java.time.LocalDateTime;
23 | import java.util.UUID;
24 |
25 |
26 | @Data
27 | @TableName("jcpp_order")
28 | @Builder
29 | @AllArgsConstructor
30 | @NoArgsConstructor
31 | public class Order implements Serializable {
32 |
33 | @TableId(type = IdType.INPUT)
34 | private UUID id;
35 |
36 | private String internalOrderNo;
37 |
38 | private String externalOrderNo;
39 |
40 | private String pileOrderNo;
41 |
42 | private LocalDateTime createdTime;
43 |
44 | private JsonNode additionalInfo;
45 |
46 | private LocalDateTime updatedTime;
47 |
48 | private LocalDateTime cancelledTime;
49 |
50 | private OrderStatusEnum status;
51 |
52 | private OrderTypeEnum type;
53 |
54 | private UUID creatorId;
55 |
56 | private UUID stationId;
57 |
58 | private UUID pileId;
59 |
60 | private UUID gunId;
61 |
62 | private String plateNo;
63 |
64 | private BigDecimal settlementAmount;
65 |
66 | private JsonNode settlementDetails;
67 |
68 | private BigDecimal electricityQuantity;
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Pile.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.entity;
8 |
9 | import com.baomidou.mybatisplus.annotation.IdType;
10 | import com.baomidou.mybatisplus.annotation.TableId;
11 | import com.baomidou.mybatisplus.annotation.TableName;
12 | import com.fasterxml.jackson.databind.JsonNode;
13 | import lombok.AllArgsConstructor;
14 | import lombok.Builder;
15 | import lombok.Data;
16 | import lombok.NoArgsConstructor;
17 | import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
18 | import sanbing.jcpp.app.dal.config.ibatis.enums.PileStatusEnum;
19 | import sanbing.jcpp.app.dal.config.ibatis.enums.PileTypeEnum;
20 | import sanbing.jcpp.infrastructure.cache.HasVersion;
21 |
22 | import java.io.Serializable;
23 | import java.time.LocalDateTime;
24 | import java.util.UUID;
25 |
26 | @Data
27 | @TableName(value = "jcpp_pile", autoResultMap = true)
28 | @Builder
29 | @AllArgsConstructor
30 | @NoArgsConstructor
31 | public class Pile implements Serializable, HasVersion {
32 |
33 | @TableId(type = IdType.INPUT)
34 | private UUID id;
35 |
36 | private LocalDateTime createdTime;
37 |
38 | private JsonNode additionalInfo;
39 |
40 | private String pileName;
41 |
42 | private String pileCode;
43 |
44 | private String protocol;
45 |
46 | private UUID stationId;
47 |
48 | private UUID ownerId;
49 |
50 | private OwnerTypeEnum ownerType;
51 |
52 | private String brand;
53 |
54 | private String model;
55 |
56 | private String manufacturer;
57 |
58 | private PileStatusEnum status;
59 |
60 | private PileTypeEnum type;
61 |
62 | private Integer version;
63 | }
64 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Station.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.entity;
8 |
9 | import com.baomidou.mybatisplus.annotation.IdType;
10 | import com.baomidou.mybatisplus.annotation.TableId;
11 | import com.baomidou.mybatisplus.annotation.TableName;
12 | import com.fasterxml.jackson.databind.JsonNode;
13 | import lombok.AllArgsConstructor;
14 | import lombok.Builder;
15 | import lombok.Data;
16 | import lombok.NoArgsConstructor;
17 | import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
18 | import sanbing.jcpp.app.dal.config.ibatis.enums.StationStatusEnum;
19 | import sanbing.jcpp.infrastructure.cache.HasVersion;
20 |
21 | import java.io.Serializable;
22 | import java.time.LocalDateTime;
23 | import java.util.UUID;
24 |
25 |
26 | @Data
27 | @TableName("jcpp_station")
28 | @Builder
29 | @AllArgsConstructor
30 | @NoArgsConstructor
31 | public class Station implements Serializable, HasVersion {
32 |
33 | @TableId(type = IdType.INPUT)
34 | private UUID id;
35 |
36 | private LocalDateTime createdTime;
37 |
38 | private JsonNode additionalInfo;
39 |
40 | private String stationName;
41 |
42 | private String stationCode;
43 |
44 | private UUID ownerId;
45 |
46 | private Float longitude;
47 |
48 | private Float latitude;
49 |
50 | private OwnerTypeEnum ownerType;
51 |
52 | private String province;
53 |
54 | private String city;
55 |
56 | private String county;
57 |
58 | private String address;
59 |
60 | private StationStatusEnum status;
61 |
62 | private Integer version;
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/User.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.entity;
8 |
9 | import com.baomidou.mybatisplus.annotation.IdType;
10 | import com.baomidou.mybatisplus.annotation.TableId;
11 | import com.baomidou.mybatisplus.annotation.TableName;
12 | import com.fasterxml.jackson.databind.JsonNode;
13 | import lombok.AllArgsConstructor;
14 | import lombok.Builder;
15 | import lombok.Data;
16 | import lombok.NoArgsConstructor;
17 | import sanbing.jcpp.app.dal.config.ibatis.enums.UserStatusEnum;
18 | import sanbing.jcpp.infrastructure.cache.HasVersion;
19 |
20 | import java.io.Serializable;
21 | import java.time.LocalDateTime;
22 | import java.util.UUID;
23 |
24 |
25 | @Data
26 | @TableName("jcpp_user")
27 | @Builder
28 | @AllArgsConstructor
29 | @NoArgsConstructor
30 | public class User implements Serializable, HasVersion {
31 |
32 | @TableId(type = IdType.INPUT)
33 | private UUID id;
34 |
35 | private LocalDateTime createdTime;
36 |
37 | private JsonNode additionalInfo;
38 |
39 | private UserStatusEnum status;
40 |
41 | private String userName;
42 |
43 | private JsonNode userCredentials;
44 |
45 | private Integer version;
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/mapper/GunMapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
10 | import sanbing.jcpp.app.dal.entity.Gun;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | public interface GunMapper extends BaseMapper {
16 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/mapper/OrderMapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
10 | import sanbing.jcpp.app.dal.entity.Order;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | public interface OrderMapper extends BaseMapper {
16 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/mapper/PileMapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
10 | import org.apache.ibatis.annotations.Select;
11 | import sanbing.jcpp.app.dal.entity.Pile;
12 |
13 | /**
14 | * @author baigod
15 | */
16 | public interface PileMapper extends BaseMapper {
17 |
18 | @Select("SELECT " +
19 | " * " +
20 | "FROM " +
21 | " jcpp_pile " +
22 | "WHERE " +
23 | " pile_code = #{pileCode}")
24 | Pile selectByCode(String pileCode);
25 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/mapper/StationMapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
10 | import sanbing.jcpp.app.dal.entity.Station;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | public interface StationMapper extends BaseMapper {
16 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/dal/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.dal.mapper;
8 |
9 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
10 | import sanbing.jcpp.app.dal.entity.User;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | public interface UserMapper extends BaseMapper {
16 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/repository/AbstractCachedEntityRepository.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.repository;
8 |
9 | import org.springframework.transaction.support.TransactionSynchronizationManager;
10 |
11 | import java.io.Serializable;
12 |
13 | public abstract class AbstractCachedEntityRepository extends AbstractEntityRepository {
14 |
15 | protected void publishEvictEvent(E event) {
16 | if (TransactionSynchronizationManager.isActualTransactionActive()) {
17 | eventPublisher.publishEvent(event);
18 | } else {
19 | handleEvictEvent(event);
20 | }
21 | }
22 |
23 | public abstract void handleEvictEvent(E event);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/repository/AbstractEntityRepository.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.repository;
8 |
9 | import jakarta.annotation.Resource;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.context.ApplicationEventPublisher;
12 |
13 | @Slf4j
14 | public abstract class AbstractEntityRepository {
15 |
16 | @Resource
17 | protected ApplicationEventPublisher eventPublisher;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/repository/CachedVersionedEntityRepository.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.repository;
8 |
9 | import jakarta.annotation.Resource;
10 | import sanbing.jcpp.infrastructure.cache.HasVersion;
11 | import sanbing.jcpp.infrastructure.cache.VersionedCache;
12 | import sanbing.jcpp.infrastructure.cache.VersionedCacheKey;
13 |
14 | import java.io.Serializable;
15 |
16 | public abstract class CachedVersionedEntityRepository extends AbstractCachedEntityRepository {
17 |
18 | @Resource
19 | protected VersionedCache cache;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/repository/PileRepository.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.repository;
8 |
9 | import sanbing.jcpp.app.dal.entity.Pile;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public interface PileRepository {
15 |
16 | Pile findPileByCode(String pileCode);
17 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/repository/PileRepositoryImpl.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.repository;
8 |
9 | import jakarta.annotation.Resource;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.stereotype.Repository;
12 | import org.springframework.transaction.event.TransactionalEventListener;
13 | import sanbing.jcpp.app.dal.entity.Pile;
14 | import sanbing.jcpp.app.dal.mapper.PileMapper;
15 | import sanbing.jcpp.app.service.cache.pile.PileCacheEvictEvent;
16 | import sanbing.jcpp.app.service.cache.pile.PileCacheKey;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import static sanbing.jcpp.infrastructure.util.validation.Validator.validateString;
22 |
23 | /**
24 | * @author baigod
25 | */
26 | @Repository
27 | @Slf4j
28 | public class PileRepositoryImpl extends CachedVersionedEntityRepository implements PileRepository {
29 |
30 | @Resource
31 | PileMapper pileMapper;
32 |
33 | @TransactionalEventListener(classes = PileCacheEvictEvent.class)
34 | @Override
35 | public void handleEvictEvent(PileCacheEvictEvent event) {
36 | // 如果修改或删除充电桩,需要在这里消费删除事件
37 | List toEvict = new ArrayList<>(3);
38 | toEvict.add(new PileCacheKey(event.getPileId()));
39 | toEvict.add(new PileCacheKey(event.getPileCode()));
40 | cache.evict(toEvict);
41 | }
42 |
43 | @Override
44 | public Pile findPileByCode(String pileCode) {
45 | validateString(pileCode, code -> "无效的桩编号" + pileCode);
46 | return cache.get(new PileCacheKey(pileCode),
47 | () -> pileMapper.selectByCode(pileCode));
48 | }
49 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/pile/PileCacheEvictEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.pile;
8 |
9 | import lombok.Data;
10 |
11 | import java.util.UUID;
12 |
13 | @Data
14 | public class PileCacheEvictEvent {
15 |
16 | private UUID pileId;
17 | private String pileCode;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/pile/PileCacheKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.pile;
8 |
9 | import lombok.Builder;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.Getter;
12 | import lombok.RequiredArgsConstructor;
13 | import sanbing.jcpp.infrastructure.cache.VersionedCacheKey;
14 |
15 | import java.io.Serial;
16 | import java.util.Optional;
17 | import java.util.UUID;
18 |
19 | @Getter
20 | @EqualsAndHashCode
21 | @RequiredArgsConstructor
22 | @Builder
23 | public class PileCacheKey implements VersionedCacheKey {
24 |
25 | @Serial
26 | private static final long serialVersionUID = 6366389552842340207L;
27 |
28 | private final UUID pileId;
29 | private final String pileCode;
30 |
31 | public PileCacheKey(UUID pileId) {
32 | this(pileId, null);
33 | }
34 |
35 | public PileCacheKey(String pileCode) {
36 | this(null, pileCode);
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return Optional.ofNullable(pileId).map(UUID::toString).orElse(pileCode);
42 | }
43 |
44 | @Override
45 | public boolean isVersioned() {
46 | return pileId != null;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/pile/PileCaffeineCache.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.pile;
8 |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
10 | import org.springframework.cache.CacheManager;
11 | import org.springframework.stereotype.Service;
12 | import sanbing.jcpp.app.dal.entity.Pile;
13 | import sanbing.jcpp.infrastructure.cache.CacheConstants;
14 | import sanbing.jcpp.infrastructure.cache.VersionedCaffeineCache;
15 |
16 | @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
17 | @Service("PileCache")
18 | public class PileCaffeineCache extends VersionedCaffeineCache {
19 |
20 | public PileCaffeineCache(CacheManager cacheManager) {
21 | super(cacheManager, CacheConstants.PILE_CACHE);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/pile/PileRedisCache.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.pile;
8 |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
10 | import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
11 | import org.springframework.data.redis.serializer.SerializationException;
12 | import org.springframework.stereotype.Service;
13 | import sanbing.jcpp.app.dal.entity.Pile;
14 | import sanbing.jcpp.infrastructure.cache.*;
15 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
16 |
17 | @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
18 | @Service("PileCache")
19 | public class PileRedisCache extends VersionedRedisCache {
20 |
21 | public PileRedisCache(JCPPRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, LettuceConnectionFactory connectionFactory) {
22 | super(CacheConstants.PILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new JCPPRedisSerializer<>() {
23 |
24 | @Override
25 | public byte[] serialize(Pile pile) throws SerializationException {
26 | return JacksonUtil.writeValueAsBytes(pile);
27 | }
28 |
29 | @Override
30 | public Pile deserialize(PileCacheKey key, byte[] bytes) throws SerializationException {
31 | return JacksonUtil.fromBytes(bytes, Pile.class);
32 | }
33 | });
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/session/PileSessionCacheKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.session;
8 |
9 | import lombok.Builder;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.Getter;
12 |
13 | import java.io.Serializable;
14 |
15 | /**
16 | * @author baigod
17 | */
18 | @Getter
19 | @EqualsAndHashCode
20 | @Builder
21 | public class PileSessionCacheKey implements Serializable {
22 |
23 | private final String pileCode;
24 |
25 | public PileSessionCacheKey(String pileCode) {
26 | this.pileCode = pileCode;
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return pileCode;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/session/PileSessionCaffeineCache.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.session;
8 |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
10 | import org.springframework.cache.CacheManager;
11 | import org.springframework.stereotype.Service;
12 | import sanbing.jcpp.app.data.PileSession;
13 | import sanbing.jcpp.infrastructure.cache.CacheConstants;
14 | import sanbing.jcpp.infrastructure.cache.CaffeineTransactionalCache;
15 |
16 | /**
17 | * @author baigod
18 | */
19 | @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
20 | @Service("PileSessionCache")
21 | public class PileSessionCaffeineCache extends CaffeineTransactionalCache {
22 |
23 | public PileSessionCaffeineCache(CacheManager cacheManager) {
24 | super(cacheManager, CacheConstants.PILE_SESSION_CACHE);
25 | }
26 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/cache/session/PileSessionRedisCache.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.cache.session;
8 |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
10 | import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
11 | import org.springframework.data.redis.serializer.SerializationException;
12 | import org.springframework.stereotype.Service;
13 | import sanbing.jcpp.app.data.PileSession;
14 | import sanbing.jcpp.infrastructure.cache.*;
15 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
16 |
17 | /**
18 | * @author baigod
19 | */
20 | @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
21 | @Service("PileSessionCache")
22 | public class PileSessionRedisCache extends RedisTransactionalCache {
23 |
24 | public PileSessionRedisCache(JCPPRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, LettuceConnectionFactory connectionFactory) {
25 | super(CacheConstants.PILE_SESSION_CACHE, cacheSpecsMap, connectionFactory, configuration, new JCPPRedisSerializer<>() {
26 |
27 | @Override
28 | public byte[] serialize(PileSession pileSession) throws SerializationException {
29 | return JacksonUtil.writeValueAsBytes(pileSession);
30 | }
31 |
32 | @Override
33 | public PileSession deserialize(PileSessionCacheKey key, byte[] bytes) throws SerializationException {
34 | return JacksonUtil.fromBytes(bytes, PileSession.class);
35 | }
36 | });
37 | }
38 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/config/DownlinkRestTemplateConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.config;
8 |
9 | import org.springframework.boot.web.client.RestTemplateBuilder;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
13 | import org.springframework.web.client.RestTemplate;
14 |
15 | import java.time.Duration;
16 | import java.time.temporal.ChronoUnit;
17 | import java.util.Collections;
18 |
19 | /**
20 | * @author baigod
21 | */
22 | @Configuration
23 | public class DownlinkRestTemplateConfiguration {
24 |
25 | @Bean("downlinkRestTemplate")
26 | public RestTemplate downlinkRestTemplate() {
27 | RestTemplate restTemplate = new RestTemplateBuilder()
28 | .setConnectTimeout(Duration.of(3, ChronoUnit.SECONDS))
29 | .setReadTimeout(Duration.of(3, ChronoUnit.SECONDS))
30 | .build();
31 | restTemplate.setMessageConverters(Collections.singletonList(new ProtobufHttpMessageConverter()));
32 | return restTemplate;
33 | }
34 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/GrpcDownlinkCallService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.impl;
8 |
9 | import com.google.common.net.HostAndPort;
10 | import jakarta.annotation.Resource;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
13 | import org.springframework.stereotype.Service;
14 | import sanbing.jcpp.app.service.DownlinkCallService;
15 | import sanbing.jcpp.app.service.grpc.DownlinkGrpcClient;
16 | import sanbing.jcpp.proto.gen.ProtocolProto.DownlinkRequestMessage;
17 | import sanbing.jcpp.proto.gen.ProtocolProto.RequestMsg;
18 |
19 | import static sanbing.jcpp.infrastructure.proto.ProtoConverter.toTracerProto;
20 |
21 | /**
22 | * @author baigod
23 | */
24 | @Service
25 | @Slf4j
26 | @ConditionalOnExpression("'${service.downlink.rpc.type:null}'=='grpc'")
27 | public class GrpcDownlinkCallService extends DownlinkCallService {
28 |
29 | @Resource
30 | DownlinkGrpcClient downlinkGrpcClient;
31 |
32 | @Override
33 | protected int determinePort(int restPort, int grpcPort) {
34 | return grpcPort;
35 | }
36 |
37 | @Override
38 | protected void _sendDownlinkMessage(DownlinkRequestMessage downlinkMessage, String nodeIp, int port) {
39 | try {
40 | RequestMsg requestMsg = RequestMsg.newBuilder()
41 | .setTs(System.currentTimeMillis())
42 | .setTracer(toTracerProto())
43 | .setDownlinkRequestMessage(downlinkMessage)
44 | .build();
45 |
46 | downlinkGrpcClient.sendDownlinkRequest(HostAndPort.fromParts(nodeIp, port), requestMsg);
47 | } catch (Exception e) {
48 | log.error("下行消息发送异常", e);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/QueueConsumerManagerTask.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.queue;
8 |
9 | import lombok.AllArgsConstructor;
10 | import lombok.Getter;
11 | import lombok.ToString;
12 | import sanbing.jcpp.infrastructure.queue.common.QueueConfig;
13 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
14 |
15 | import java.util.Set;
16 |
17 | @Getter
18 | @ToString
19 | @AllArgsConstructor
20 | public class QueueConsumerManagerTask {
21 |
22 | private final QueueEvent event;
23 | private QueueConfig config;
24 | private Set partitions;
25 | private boolean drainQueue;
26 |
27 | public static QueueConsumerManagerTask delete(boolean drainQueue) {
28 | return new QueueConsumerManagerTask(QueueEvent.DELETE, null, null, drainQueue);
29 | }
30 |
31 | public static QueueConsumerManagerTask configUpdate(QueueConfig config) {
32 | return new QueueConsumerManagerTask(QueueEvent.CONFIG_UPDATE, config, null, false);
33 | }
34 |
35 | public static QueueConsumerManagerTask partitionChange(Set partitions) {
36 | return new QueueConsumerManagerTask(QueueEvent.PARTITION_CHANGE, null, partitions, false);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/QueueEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.app.service.queue;
8 |
9 | import java.io.Serializable;
10 |
11 | public enum QueueEvent implements Serializable {
12 |
13 | PARTITION_CHANGE, CONFIG_UPDATE, DELETE
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
13 |
14 | sanbing
15 | jcpp-parent
16 | 1.0.0-SNAPSHOT
17 | ../pom.xml
18 |
19 | 4.0.0
20 |
21 | jcpp-infrastructure-cache
22 | jar
23 | JChargePointProtocol Infrastructure Cache Module
24 | 基础缓存管理模块
25 |
26 |
27 | ${basedir}/..
28 |
29 |
30 |
31 |
32 | org.springframework.data
33 | spring-data-redis
34 |
35 |
36 | io.lettuce
37 | lettuce-core
38 |
39 |
40 | org.apache.commons
41 | commons-pool2
42 |
43 |
44 | sanbing
45 | jcpp-infrastructure-util
46 |
47 |
48 | com.github.ben-manes.caffeine
49 | caffeine
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CacheConstants.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | public final class CacheConstants {
10 |
11 | public static final String PILE_CACHE = "piles";
12 |
13 | public static final String PILE_SESSION_CACHE = "pileSessions";
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CacheSpecs.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import lombok.Data;
10 |
11 | @Data
12 | public class CacheSpecs {
13 | private Integer timeToLiveInMinutes;
14 | private Integer maxSize;
15 | }
16 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CacheSpecsMap.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import lombok.Data;
10 | import lombok.Getter;
11 | import org.springframework.boot.context.properties.ConfigurationProperties;
12 | import org.springframework.context.annotation.Configuration;
13 |
14 | import java.util.Map;
15 |
16 | @Configuration
17 | @ConfigurationProperties(prefix = "cache")
18 | @Data
19 | public class CacheSpecsMap {
20 |
21 | @Getter
22 | private Map specs;
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CacheTransaction.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | public interface CacheTransaction {
10 |
11 | void put(K key, V value);
12 |
13 | boolean commit();
14 |
15 | void rollback();
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CacheValueWrapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | public interface CacheValueWrapper {
10 |
11 | T get();
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/CaffeineCacheTransaction.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import lombok.Getter;
10 | import lombok.RequiredArgsConstructor;
11 | import lombok.Setter;
12 | import lombok.extern.slf4j.Slf4j;
13 |
14 | import java.io.Serializable;
15 | import java.util.LinkedHashMap;
16 | import java.util.List;
17 | import java.util.Map;
18 | import java.util.UUID;
19 |
20 | @Slf4j
21 | @RequiredArgsConstructor
22 | public class CaffeineCacheTransaction implements CacheTransaction {
23 | @Getter
24 | private final UUID id = UUID.randomUUID();
25 | private final CaffeineTransactionalCache cache;
26 | @Getter
27 | private final List keys;
28 | @Getter
29 | @Setter
30 | private boolean failed;
31 |
32 | private final Map pendingPuts = new LinkedHashMap<>();
33 |
34 | @Override
35 | public void put(K key, V value) {
36 | pendingPuts.put(key, value);
37 | }
38 |
39 | @Override
40 | public boolean commit() {
41 | return cache.commit(id, pendingPuts);
42 | }
43 |
44 | @Override
45 | public void rollback() {
46 | cache.rollback(id);
47 | }
48 |
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/HasVersion.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | public interface HasVersion {
10 |
11 | Integer getVersion();
12 |
13 | default void setVersion(Integer version) {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/JCPPRedisSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import org.springframework.data.redis.serializer.SerializationException;
10 | import org.springframework.lang.Nullable;
11 |
12 | public interface JCPPRedisSerializer {
13 |
14 | @Nullable
15 | byte[] serialize(@Nullable T t) throws SerializationException;
16 |
17 | @Nullable
18 | T deserialize(K key, @Nullable byte[] bytes) throws SerializationException;
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/RedisCacheTransaction.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import lombok.RequiredArgsConstructor;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.data.redis.connection.RedisConnection;
12 |
13 | import java.io.Serializable;
14 | import java.util.Objects;
15 |
16 | @Slf4j
17 | @RequiredArgsConstructor
18 | public class RedisCacheTransaction implements CacheTransaction {
19 |
20 | private final RedisTransactionalCache cache;
21 | private final RedisConnection connection;
22 |
23 | @Override
24 | public void put(K key, V value) {
25 | cache.put(key, value, connection);
26 | }
27 |
28 | @Override
29 | public boolean commit() {
30 | try {
31 | var execResult = connection.exec();
32 | return execResult.stream().anyMatch(Objects::nonNull);
33 | } finally {
34 | connection.close();
35 | }
36 | }
37 |
38 | @Override
39 | public void rollback() {
40 | try {
41 | connection.discard();
42 | } finally {
43 | connection.close();
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/SimpleCacheValueWrapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import lombok.AccessLevel;
10 | import lombok.RequiredArgsConstructor;
11 | import lombok.ToString;
12 | import org.springframework.cache.Cache;
13 |
14 | @ToString
15 | @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
16 | public class SimpleCacheValueWrapper implements CacheValueWrapper {
17 |
18 | private final T value;
19 |
20 | @Override
21 | public T get() {
22 | return value;
23 | }
24 |
25 | public static SimpleCacheValueWrapper empty() {
26 | return new SimpleCacheValueWrapper<>(null);
27 | }
28 |
29 | public static SimpleCacheValueWrapper wrap(T value) {
30 | return new SimpleCacheValueWrapper<>(value);
31 | }
32 |
33 | @SuppressWarnings("unchecked")
34 | public static SimpleCacheValueWrapper wrap(Cache.ValueWrapper source) {
35 | return source == null ? null : new SimpleCacheValueWrapper<>((T) source.get());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/VersionedCache.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 |
10 | import java.io.Serializable;
11 | import java.util.Collection;
12 | import java.util.Optional;
13 | import java.util.function.Supplier;
14 |
15 | public interface VersionedCache extends TransactionalCache {
16 |
17 | CacheValueWrapper get(K key);
18 |
19 | default V get(K key, Supplier supplier) {
20 | return get(key, supplier, true);
21 | }
22 |
23 | default V get(K key, Supplier supplier, boolean putToCache) {
24 | return Optional.ofNullable(get(key))
25 | .map(CacheValueWrapper::get)
26 | .orElseGet(() -> {
27 | V value = supplier.get();
28 | if (putToCache) {
29 | put(key, value);
30 | }
31 | return value;
32 | });
33 | }
34 |
35 | void put(K key, V value);
36 |
37 | void evict(K key);
38 |
39 | void evict(Collection keys);
40 |
41 | void evict(K key, Integer version);
42 |
43 | default Integer getVersion(V value) {
44 | if (value == null) {
45 | return 0;
46 | } else if (value.getVersion() != null) {
47 | return value.getVersion();
48 | } else {
49 | return null;
50 | }
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-cache/src/main/java/sanbing/jcpp/infrastructure/cache/VersionedCacheKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.cache;
8 |
9 | import java.io.Serializable;
10 |
11 | public interface VersionedCacheKey extends Serializable {
12 |
13 | default boolean isVersioned() {
14 | return false;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-proto/src/main/java/sanbing/jcpp/infrastructure/proto/model/PricingModel.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.proto.model;
8 |
9 | import lombok.*;
10 | import sanbing.jcpp.proto.gen.ProtocolProto.PricingModelFlag;
11 | import sanbing.jcpp.proto.gen.ProtocolProto.PricingModelRule;
12 | import sanbing.jcpp.proto.gen.ProtocolProto.PricingModelType;
13 |
14 | import java.math.BigDecimal;
15 | import java.time.LocalTime;
16 | import java.util.List;
17 | import java.util.Map;
18 | import java.util.UUID;
19 |
20 | @Data
21 | public class PricingModel {
22 |
23 | private UUID id;
24 |
25 | // 计数器,供充电桩协议使用
26 | private int sequenceNumber;
27 |
28 | private String pileCode;
29 |
30 | private PricingModelType type;
31 |
32 | private PricingModelRule rule;
33 |
34 | /**
35 | * 标准电价(单位元)
36 | */
37 | private BigDecimal standardElec;
38 |
39 | /**
40 | * 标准服务费(单位元)
41 | */
42 | private BigDecimal standardServ;
43 |
44 | /**
45 | * 分时电价
46 | */
47 | private Map flagPriceList;
48 |
49 | /**
50 | * 分时时段
51 | */
52 | private List periodsList;
53 |
54 | @Setter
55 | @Getter
56 | public static class Period {
57 | private int sn;
58 |
59 | // 起始时间
60 | private LocalTime begin;
61 |
62 | // 结束时间
63 | private LocalTime end;
64 |
65 | // 尖峰平谷标识
66 | private PricingModelFlag flag;
67 | }
68 |
69 | @Data
70 | @AllArgsConstructor
71 | @NoArgsConstructor
72 | public static class FlagPrice {
73 |
74 | // 分时电价,单位元
75 | private BigDecimal elec;
76 |
77 | // 分时服务费,单位元
78 | private BigDecimal serv;
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-proto/src/main/proto/cluster.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | syntax = "proto3";
8 |
9 | package infrastructureProto;
10 |
11 | option java_package = "sanbing.jcpp.proto.gen";
12 | option java_outer_classname = "ClusterProto";
13 |
14 | message ServiceInfo {
15 | string serviceId = 1;
16 | repeated string serviceTypes = 2;
17 | SystemInfoProto systemInfo = 10;
18 | }
19 |
20 | message SystemInfoProto {
21 | int64 cpuUsage = 1;
22 | int64 cpuCount = 2;
23 | int64 memoryUsage = 3;
24 | int64 totalMemory = 4;
25 | int64 diskUsage = 5;
26 | int64 totalDiscSpace = 6;
27 | }
28 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
13 |
14 | sanbing
15 | jcpp-parent
16 | 1.0.0-SNAPSHOT
17 | ../pom.xml
18 |
19 | 4.0.0
20 |
21 | jcpp-infrastructure-queue
22 | jar
23 | JChargePointProtocol Infrastructure Queue Module
24 | 基础MQ管理模块
25 |
26 |
27 | ${basedir}/..
28 |
29 |
30 |
31 |
32 | org.apache.kafka
33 | kafka-clients
34 |
35 |
36 | sanbing
37 | jcpp-infrastructure-util
38 |
39 |
40 | sanbing
41 | jcpp-infrastructure-proto
42 |
43 |
44 | sanbing
45 | jcpp-infrastructure-stats
46 |
47 |
48 | org.apache.curator
49 | curator-recipes
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/Callback.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | public interface Callback {
10 |
11 | Callback EMPTY = new Callback() {
12 |
13 | @Override
14 | public void onSuccess() {
15 |
16 | }
17 |
18 | @Override
19 | public void onFailure(Throwable t) {
20 |
21 | }
22 | };
23 |
24 | void onSuccess();
25 |
26 | void onFailure(Throwable t);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/DefaultQueueMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | import lombok.Data;
10 |
11 | @Data
12 | public class DefaultQueueMsg implements QueueMsg {
13 | private final String key;
14 | private final byte[] data;
15 | private final DefaultQueueMsgHeaders headers;
16 |
17 | public DefaultQueueMsg(QueueMsg msg) {
18 | this.key = msg.getKey();
19 | this.data = msg.getData();
20 | DefaultQueueMsgHeaders headers = new DefaultQueueMsgHeaders();
21 | msg.getHeaders().getData().forEach(headers::put);
22 | this.headers = headers;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/DefaultQueueMsgHeaders.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 |
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | public class DefaultQueueMsgHeaders implements QueueMsgHeaders {
14 |
15 | protected final Map data = new HashMap<>();
16 |
17 | @Override
18 | public byte[] put(String key, byte[] value) {
19 | return data.put(key, value);
20 | }
21 |
22 | @Override
23 | public byte[] get(String key) {
24 | return data.get(key);
25 | }
26 |
27 | @Override
28 | public Map getData() {
29 | return data;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/KafkaQueueMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | import org.apache.kafka.clients.consumer.ConsumerRecord;
10 |
11 | public class KafkaQueueMsg implements QueueMsg {
12 | private final String key;
13 | private final QueueMsgHeaders headers;
14 | private final byte[] data;
15 |
16 | public KafkaQueueMsg(ConsumerRecord record) {
17 | this.key = record.key();
18 | QueueMsgHeaders headers = new DefaultQueueMsgHeaders();
19 | record.headers().forEach(header -> {
20 | headers.put(header.key(), header.value());
21 | });
22 | this.headers = headers;
23 | this.data = record.value();
24 | }
25 |
26 | @Override
27 | public String getKey() {
28 | return key;
29 | }
30 |
31 | @Override
32 | public QueueMsgHeaders getHeaders() {
33 | return headers;
34 | }
35 |
36 | @Override
37 | public byte[] getData() {
38 | return data;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/PackCallback.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | import lombok.extern.slf4j.Slf4j;
10 |
11 | import java.util.UUID;
12 |
13 | @Slf4j
14 | public class PackCallback implements Callback {
15 | private final PackProcessingContext ctx;
16 | private final UUID id;
17 |
18 | public PackCallback(UUID id, PackProcessingContext ctx) {
19 | this.id = id;
20 | this.ctx = ctx;
21 | }
22 |
23 | @Override
24 | public void onSuccess() {
25 | log.trace("[{}] ON SUCCESS", id);
26 | ctx.onSuccess(id);
27 | }
28 |
29 | @Override
30 | public void onFailure(Throwable t) {
31 | log.trace("[{}] ON FAILURE", id, t);
32 | ctx.onFailure(id, t);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/ProtoQueueMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | import com.google.protobuf.GeneratedMessage;
10 | import lombok.Data;
11 |
12 | @Data
13 | public class ProtoQueueMsg implements QueueMsg {
14 |
15 | private final String key;
16 | protected final T value;
17 | private final QueueMsgHeaders headers;
18 |
19 | public ProtoQueueMsg(String key, T value) {
20 | this(key, value, new DefaultQueueMsgHeaders());
21 | }
22 |
23 | public ProtoQueueMsg(String key, T value, QueueMsgHeaders headers) {
24 | this.key = key;
25 | this.value = value;
26 | this.headers = headers;
27 | }
28 |
29 | @Override
30 | public String getKey() {
31 | return key;
32 | }
33 |
34 | @Override
35 | public QueueMsgHeaders getHeaders() {
36 | return headers;
37 | }
38 |
39 | @Override
40 | public byte[] getData() {
41 | return value.toByteArray();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueAdmin.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | public interface QueueAdmin {
10 |
11 | default void createTopicIfNotExists(String topic) {
12 | createTopicIfNotExists(topic, null);
13 | }
14 |
15 | void createTopicIfNotExists(String topic, String properties);
16 |
17 | void destroy();
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueCallback.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | public interface QueueCallback {
10 |
11 | void onSuccess(QueueMsgMetadata metadata);
12 |
13 | void onFailure(Throwable t);
14 | }
15 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueConsumer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 |
10 |
11 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
12 |
13 | import java.util.List;
14 | import java.util.Set;
15 |
16 | public interface QueueConsumer {
17 |
18 | String getTopic();
19 |
20 | void subscribe();
21 |
22 | void subscribe(Set partitions);
23 |
24 | void stop();
25 |
26 | void unsubscribe();
27 |
28 | List poll(long durationInMillis);
29 |
30 | void commit();
31 |
32 | boolean isStopped();
33 |
34 | List getFullTopicNames();
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | public interface QueueMsg {
10 |
11 | String getKey();
12 |
13 | QueueMsgHeaders getHeaders();
14 |
15 | byte[] getData();
16 | }
17 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueMsgHeaders.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | import java.util.Map;
10 |
11 | public interface QueueMsgHeaders {
12 |
13 | byte[] put(String key, byte[] value);
14 |
15 | byte[] get(String key);
16 |
17 | Map getData();
18 | }
19 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueMsgMetadata.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 | public interface QueueMsgMetadata {
10 | }
11 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/QueueProducer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
11 |
12 | public interface QueueProducer {
13 |
14 | void init();
15 |
16 | String getTopic();
17 |
18 | void send(TopicPartitionInfo tpi, T msg, QueueCallback callback);
19 |
20 | void stop();
21 | }
22 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/common/QueueConfig.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.common;
8 |
9 | public interface QueueConfig {
10 |
11 | boolean isConsumerPerPartition();
12 |
13 | int getPollInterval();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/common/QueueConstants.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.common;
8 |
9 | import static sanbing.jcpp.infrastructure.util.trace.TracerContextUtil.*;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public final class QueueConstants {
15 |
16 | public static final String MSG_MD_PREFIX = "jcpp_";
17 |
18 | public static final String MSG_MD_TRACER_ID = MSG_MD_PREFIX + JCPP_TRACER_ID;
19 |
20 | public static final String MSG_MD_TRACER_ORIGIN = MSG_MD_PREFIX + JCPP_TRACER_ORIGIN;
21 |
22 | public static final String MSG_MD_TRACER_TS = MSG_MD_PREFIX + JCPP_TRACER_TS;
23 |
24 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/common/TopicPartitionInfo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.common;
8 |
9 | import lombok.Builder;
10 | import lombok.Getter;
11 | import lombok.ToString;
12 |
13 | import java.util.Objects;
14 | import java.util.Optional;
15 |
16 | @ToString
17 | public class TopicPartitionInfo {
18 |
19 | @Getter
20 | private final String topic;
21 | private final Integer partition;
22 | @Getter
23 | private final String fullTopicName;
24 | @Getter
25 | private final boolean myPartition;
26 |
27 | @Builder
28 | public TopicPartitionInfo(String topic, Integer partition, boolean myPartition) {
29 | this.topic = topic;
30 | this.partition = partition;
31 | this.myPartition = myPartition;
32 | String tmp = topic;
33 | if (partition != null) {
34 | tmp += "." + partition;
35 | }
36 | this.fullTopicName = tmp;
37 | }
38 |
39 | public TopicPartitionInfo newByTopic(String topic) {
40 | return new TopicPartitionInfo(topic, this.partition, this.myPartition);
41 | }
42 |
43 | public Optional getPartition() {
44 | return Optional.ofNullable(partition);
45 | }
46 |
47 | @Override
48 | public boolean equals(Object o) {
49 | if (this == o) return true;
50 | if (o == null || getClass() != o.getClass()) return false;
51 | TopicPartitionInfo that = (TopicPartitionInfo) o;
52 | return topic.equals(that.topic) &&
53 | Objects.equals(partition, that.partition) &&
54 | fullTopicName.equals(that.fullTopicName);
55 | }
56 |
57 | @Override
58 | public int hashCode() {
59 | return Objects.hash(fullTopicName);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/DiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 | import sanbing.jcpp.proto.gen.ClusterProto.ServiceInfo;
10 |
11 | import java.util.List;
12 |
13 | public interface DiscoveryProvider {
14 |
15 | List getOtherServers();
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/DummyDiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
11 | import org.springframework.boot.context.event.ApplicationReadyEvent;
12 | import org.springframework.stereotype.Service;
13 | import sanbing.jcpp.infrastructure.util.annotation.AfterStartUp;
14 | import sanbing.jcpp.proto.gen.ClusterProto.ServiceInfo;
15 |
16 | import java.util.Collections;
17 | import java.util.List;
18 |
19 | @Service
20 | @ConditionalOnProperty(prefix = "zk", value = "enabled", havingValue = "false", matchIfMissing = true)
21 | @Slf4j
22 | public class DummyDiscoveryProvider implements DiscoveryProvider {
23 |
24 | private final ServiceInfoProvider serviceInfoProvider;
25 | private final PartitionProvider partitionProvider;
26 |
27 | public DummyDiscoveryProvider(ServiceInfoProvider serviceInfoProvider, PartitionProvider partitionProvider) {
28 | this.serviceInfoProvider = serviceInfoProvider;
29 | this.partitionProvider = partitionProvider;
30 | }
31 |
32 |
33 | @AfterStartUp(order = AfterStartUp.DISCOVERY_SERVICE)
34 | public void onApplicationEvent(ApplicationReadyEvent event) {
35 | partitionProvider.recalculatePartitions(serviceInfoProvider.getServiceInfo(), Collections.emptyList());
36 | }
37 |
38 | @Override
39 | public List getOtherServers() {
40 | return Collections.emptyList();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/PartitionProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
11 | import sanbing.jcpp.proto.gen.ClusterProto.ServiceInfo;
12 |
13 | import java.util.List;
14 | import java.util.UUID;
15 |
16 | public interface PartitionProvider {
17 |
18 | TopicPartitionInfo resolve(ServiceType serviceType,String queueName, UUID entityId);
19 |
20 | TopicPartitionInfo resolve(ServiceType serviceType,String queueName, String pileCode);
21 |
22 | void recalculatePartitions(ServiceInfo currentService, List otherServices);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/QueueKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 | import lombok.Data;
10 | import lombok.With;
11 |
12 | @Data
13 | public class QueueKey {
14 | public static final String MAIN_QUEUE_NAME = "Main";
15 |
16 | private final ServiceType type;
17 | @With
18 | private final String queueName;
19 |
20 | public QueueKey(ServiceType type, String queueName) {
21 | this.type = type;
22 | this.queueName = queueName;
23 | }
24 |
25 | public QueueKey(ServiceType type) {
26 | this.type = type;
27 | this.queueName = MAIN_QUEUE_NAME;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "QK(" + queueName + "," + type + ")";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/ServiceInfoProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 |
10 | import sanbing.jcpp.proto.gen.ClusterProto;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | public interface ServiceInfoProvider {
16 | String getServiceId();
17 |
18 | String getHostAddress();
19 |
20 | int getRestPort();
21 |
22 | int getGrpcPort();
23 |
24 | String getServiceType();
25 |
26 | boolean isMonolith();
27 |
28 | ClusterProto.ServiceInfo getServiceInfo();
29 |
30 | ClusterProto.ServiceInfo generateNewServiceInfoWithCurrentSystemInfo();
31 |
32 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/ServiceType.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery;
8 |
9 | import lombok.Getter;
10 | import lombok.RequiredArgsConstructor;
11 |
12 | @RequiredArgsConstructor
13 | @Getter
14 | public enum ServiceType {
15 |
16 | APP("app"),
17 | PROTOCOL("protocol");
18 |
19 | private final String label;
20 |
21 | public static ServiceType of(String serviceType) {
22 | return ServiceType.valueOf(serviceType.toUpperCase());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/event/JCPPApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery.event;
8 |
9 | import lombok.Getter;
10 | import lombok.ToString;
11 | import org.springframework.context.ApplicationEvent;
12 |
13 | import java.util.concurrent.atomic.AtomicInteger;
14 |
15 | @ToString
16 | public class JCPPApplicationEvent extends ApplicationEvent {
17 |
18 | private static final AtomicInteger sequence = new AtomicInteger();
19 |
20 | @Getter
21 | private final int sequenceNumber;
22 |
23 | public JCPPApplicationEvent(Object source) {
24 | super(source);
25 | sequenceNumber = sequence.incrementAndGet();
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/event/OtherServiceShutdownEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery.event;
8 |
9 | import lombok.Getter;
10 |
11 | public class OtherServiceShutdownEvent extends JCPPApplicationEvent {
12 |
13 | @Getter
14 | private final String serviceId;
15 |
16 | public OtherServiceShutdownEvent(Object source, String serviceId) {
17 | super(source);
18 | this.serviceId = serviceId;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/discovery/event/PartitionChangeEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.discovery.event;
8 |
9 | import lombok.Getter;
10 | import lombok.ToString;
11 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
12 | import sanbing.jcpp.infrastructure.queue.discovery.QueueKey;
13 | import sanbing.jcpp.infrastructure.queue.discovery.ServiceType;
14 |
15 | import java.io.Serial;
16 | import java.util.Map;
17 | import java.util.Set;
18 | import java.util.stream.Collectors;
19 |
20 | import static sanbing.jcpp.infrastructure.queue.discovery.QueueKey.MAIN_QUEUE_NAME;
21 |
22 | @ToString(callSuper = true)
23 | public class PartitionChangeEvent extends JCPPApplicationEvent {
24 |
25 | @Serial
26 | private static final long serialVersionUID = -8731788167026510559L;
27 |
28 | @Getter
29 | private final Map> partitionsMap;
30 |
31 | public PartitionChangeEvent(Object source, ServiceType serviceType, Map> partitionsMap) {
32 | super(source);
33 | this.partitionsMap = partitionsMap;
34 | }
35 |
36 | public Set getAppPartitions() {
37 | return getPartitionsByServiceTypeAndQueueName(ServiceType.APP, MAIN_QUEUE_NAME);
38 | }
39 |
40 | private Set getPartitionsByServiceTypeAndQueueName(ServiceType serviceType, String queueName) {
41 | return partitionsMap.entrySet()
42 | .stream()
43 | .filter(entry -> serviceType.equals(entry.getKey().getType()) && queueName.equals(entry.getKey().getQueueName()))
44 | .flatMap(entry -> entry.getValue().stream())
45 | .collect(Collectors.toSet());
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaConsumerStatisticConfig.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.kafka;
8 |
9 | import lombok.AllArgsConstructor;
10 | import lombok.Getter;
11 | import lombok.NoArgsConstructor;
12 | import org.springframework.beans.factory.annotation.Value;
13 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | @ConditionalOnProperty(prefix = "queue", value = "type", havingValue = "kafka")
18 | @Getter
19 | @AllArgsConstructor
20 | @NoArgsConstructor
21 | public class KafkaConsumerStatisticConfig {
22 |
23 | @Value("${queue.kafka.consumer-stats.enabled:true}")
24 | private Boolean enabled;
25 |
26 | @Value("${queue.kafka.consumer-stats.print-interval-ms:60000}")
27 | private Long printIntervalMs;
28 |
29 | @Value("${queue.kafka.consumer-stats.kafka-response-timeout-ms:1000}")
30 | private Long kafkaResponseTimeoutMs;
31 | }
32 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.kafka;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.queue.QueueMsg;
11 |
12 | import java.io.IOException;
13 |
14 | public interface KafkaDecoder {
15 |
16 | T decode(QueueMsg msg) throws IOException;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaQueueMsgMetadata.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.kafka;
8 |
9 | import lombok.AllArgsConstructor;
10 | import lombok.Data;
11 | import org.apache.kafka.clients.producer.RecordMetadata;
12 | import sanbing.jcpp.infrastructure.queue.QueueMsgMetadata;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | public class KafkaQueueMsgMetadata implements QueueMsgMetadata {
17 |
18 | private RecordMetadata metadata;
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/kafka/KafkaTopicConfigs.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.kafka;
8 |
9 | import jakarta.annotation.PostConstruct;
10 | import lombok.Getter;
11 | import org.springframework.beans.factory.annotation.Value;
12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
13 | import org.springframework.stereotype.Component;
14 | import sanbing.jcpp.infrastructure.util.property.PropertyUtils;
15 |
16 | import java.util.Map;
17 |
18 | @Component
19 | @ConditionalOnProperty(prefix = "queue", value = "type", havingValue = "kafka")
20 | public class KafkaTopicConfigs {
21 | public static final String NUM_PARTITIONS_SETTING = "partitions";
22 |
23 | @Value("${queue.kafka.topic-properties.app:}")
24 | private String appProperties;
25 |
26 | @Getter
27 | private Map appConfigs;
28 |
29 | @PostConstruct
30 | private void init() {
31 | this.appConfigs = PropertyUtils.getProps(appProperties);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/memory/InMemoryQueueProducer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.memory;
8 |
9 | import lombok.Data;
10 | import sanbing.jcpp.infrastructure.queue.QueueCallback;
11 | import sanbing.jcpp.infrastructure.queue.QueueMsg;
12 | import sanbing.jcpp.infrastructure.queue.QueueProducer;
13 | import sanbing.jcpp.infrastructure.queue.common.TopicPartitionInfo;
14 |
15 | @Data
16 | public class InMemoryQueueProducer implements QueueProducer {
17 | private final InMemoryStorage storage;
18 |
19 | private final String topic;
20 |
21 | public InMemoryQueueProducer(InMemoryStorage storage, String topic) {
22 | this.storage = storage;
23 | this.topic = topic;
24 | }
25 |
26 | @Override
27 | public void init() {
28 |
29 | }
30 |
31 | @Override
32 | public void send(TopicPartitionInfo tpi, T msg, QueueCallback callback) {
33 | boolean result = storage.put(tpi.getFullTopicName(), msg);
34 | if (result) {
35 | if (callback != null) {
36 | callback.onSuccess(null);
37 | }
38 | } else {
39 | if (callback != null) {
40 | callback.onFailure(new RuntimeException("Failure add msg to InMemoryQueue"));
41 | }
42 | }
43 | }
44 |
45 | @Override
46 | public void stop() {
47 |
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/memory/InMemoryStorage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.memory;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.queue.QueueMsg;
11 |
12 | import java.util.List;
13 |
14 | public interface InMemoryStorage {
15 |
16 | void printStats();
17 |
18 | int getLagTotal();
19 |
20 | int getLag(String topic);
21 |
22 | boolean put(String topic, QueueMsg msg);
23 |
24 | List get(String topic) throws InterruptedException;
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/processing/IdMsgPair.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.processing;
8 |
9 | import com.google.protobuf.GeneratedMessage;
10 | import lombok.Getter;
11 | import sanbing.jcpp.infrastructure.queue.ProtoQueueMsg;
12 |
13 | import java.util.UUID;
14 |
15 | public class IdMsgPair {
16 | @Getter
17 | final UUID uuid;
18 | @Getter
19 | final ProtoQueueMsg msg;
20 |
21 | public IdMsgPair(UUID uuid, ProtoQueueMsg msg) {
22 | this.uuid = uuid;
23 | this.msg = msg;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/provider/AppQueueFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.provider;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.queue.ProtoQueueMsg;
11 | import sanbing.jcpp.infrastructure.queue.QueueConsumer;
12 | import sanbing.jcpp.infrastructure.queue.QueueProducer;
13 | import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
14 |
15 | public interface AppQueueFactory {
16 |
17 | QueueConsumer> createProtocolUplinkMsgConsumer();
18 |
19 | QueueProducer> createProtocolUplinkMsgProducer(String topic);
20 | }
21 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-queue/src/main/java/sanbing/jcpp/infrastructure/queue/settings/QueueAppSettings.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.queue.settings;
8 |
9 | import lombok.Data;
10 | import org.springframework.beans.factory.annotation.Value;
11 | import org.springframework.context.annotation.Lazy;
12 | import org.springframework.stereotype.Component;
13 |
14 | @Lazy
15 | @Data
16 | @Component
17 | public class QueueAppSettings {
18 |
19 | @Value("${queue.app.topic}")
20 | private String topic;
21 |
22 | @Value("${queue.app.partitions}")
23 | private int partitions;
24 |
25 | @Value("${queue.app.decoder:protobuf}")
26 | private DecoderType decoder;
27 |
28 | public enum DecoderType {
29 | protobuf,
30 | json
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/DefaultCounter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | import io.micrometer.core.instrument.Counter;
10 |
11 | import java.util.concurrent.atomic.AtomicInteger;
12 |
13 | public class DefaultCounter {
14 | private final AtomicInteger aiCounter;
15 | private final Counter micrometerCounter;
16 |
17 | public DefaultCounter(AtomicInteger aiCounter, Counter micrometerCounter) {
18 | this.aiCounter = aiCounter;
19 | this.micrometerCounter = micrometerCounter;
20 | }
21 |
22 | public void increment() {
23 | aiCounter.incrementAndGet();
24 | micrometerCounter.increment();
25 | }
26 |
27 | public void clear() {
28 | aiCounter.set(0);
29 | }
30 |
31 | public int get() {
32 | return aiCounter.get();
33 | }
34 |
35 | public void add(int delta){
36 | aiCounter.addAndGet(delta);
37 | micrometerCounter.increment(delta);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/DefaultMessagesStats.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | public class DefaultMessagesStats implements MessagesStats {
10 | private final StatsCounter totalCounter;
11 | private final StatsCounter successfulCounter;
12 | private final StatsCounter failedCounter;
13 |
14 | public DefaultMessagesStats(StatsCounter totalCounter, StatsCounter successfulCounter, StatsCounter failedCounter) {
15 | this.totalCounter = totalCounter;
16 | this.successfulCounter = successfulCounter;
17 | this.failedCounter = failedCounter;
18 | }
19 |
20 | @Override
21 | public void incrementTotal(int amount) {
22 | totalCounter.add(amount);
23 | }
24 |
25 | @Override
26 | public void incrementSuccessful(int amount) {
27 | successfulCounter.add(amount);
28 | }
29 |
30 | @Override
31 | public void incrementFailed(int amount) {
32 | failedCounter.add(amount);
33 | }
34 |
35 | @Override
36 | public int getTotal() {
37 | return totalCounter.get();
38 | }
39 |
40 | @Override
41 | public int getSuccessful() {
42 | return successfulCounter.get();
43 | }
44 |
45 | @Override
46 | public int getFailed() {
47 | return failedCounter.get();
48 | }
49 |
50 | @Override
51 | public void reset() {
52 | totalCounter.clear();
53 | successfulCounter.clear();
54 | failedCounter.clear();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/MessagesStats.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | public interface MessagesStats {
10 | default void incrementTotal() {
11 | incrementTotal(1);
12 | }
13 |
14 | void incrementTotal(int amount);
15 |
16 | default void incrementSuccessful() {
17 | incrementSuccessful(1);
18 | }
19 |
20 | void incrementSuccessful(int amount);
21 |
22 | default void incrementFailed() {
23 | incrementFailed(1);
24 | }
25 |
26 | void incrementFailed(int amount);
27 |
28 | int getTotal();
29 |
30 | int getSuccessful();
31 |
32 | int getFailed();
33 |
34 | void reset();
35 | }
36 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/StatsCounter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | import io.micrometer.core.instrument.Counter;
10 |
11 | import java.util.concurrent.atomic.AtomicInteger;
12 |
13 | public class StatsCounter extends DefaultCounter {
14 | private final String name;
15 |
16 | public StatsCounter(AtomicInteger aiCounter, Counter micrometerCounter, String name) {
17 | super(aiCounter, micrometerCounter);
18 | this.name = name;
19 | }
20 |
21 | public String getName() {
22 | return name;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/StatsFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | import io.micrometer.core.instrument.Timer;
10 |
11 | public interface StatsFactory {
12 |
13 | /**
14 | * 创建状态计数器,默认带一个statsName的Tag,并可以自定义扩展其他Tag
15 | *
16 | * @param key 指标名
17 | * @param statsName statsName的标签值
18 | * @param otherTags 其他Tag键值对,参数个数需要是偶数
19 | * @return
20 | */
21 | StatsCounter createStatsCounter(String key, String statsName, String... otherTags);
22 |
23 | /**
24 | * 创建计数器,可自定义Tag
25 | *
26 | * @param key 指标名
27 | * @param tags 自定义Tag键值对,参数个数需要是偶数
28 | * @return
29 | */
30 | DefaultCounter createDefaultCounter(String key, String... tags);
31 |
32 | /**
33 | * 创建消息计数器,消息计数器默认包含三种状态(总数、成功数、失败数)
34 | *
35 | * @param key 指标名
36 | * @param tags 自定义Tag键值对,参数个数需要是偶数
37 | * @return
38 | */
39 | MessagesStats createMessagesStats(String key, String... tags);
40 |
41 | /**
42 | * 创建计时器
43 | *
44 | * @param key 指标名
45 | * @param tags 自定义Tag键值对,参数个数需要是偶数
46 | * @return
47 | */
48 | Timer createTimer(String key, String... tags);
49 |
50 | /**
51 | * 创建计量器,用于记录某个值的当前状态,可以是瞬时数值
52 | *
53 | * @param key 指标名
54 | * @param number 初始值
55 | * @param tags 自定义Tag键值对,参数个数需要是偶数
56 | * @return
57 | * @param
58 | */
59 | T createGauge(String key, T number, String... tags);
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-stats/src/main/java/sanbing/jcpp/infrastructure/stats/StatsTimer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.stats;
8 |
9 | import io.micrometer.core.instrument.Timer;
10 | import lombok.Getter;
11 |
12 | import java.util.concurrent.TimeUnit;
13 |
14 | public class StatsTimer {
15 |
16 | @Getter
17 | private final String name;
18 | private final Timer timer;
19 |
20 | private int count;
21 | private long totalTime;
22 |
23 | public StatsTimer(String name, Timer micrometerTimer) {
24 | this.name = name;
25 | this.timer = micrometerTimer;
26 | }
27 |
28 | public void record(long timeMs) {
29 | count++;
30 | totalTime += timeMs;
31 | timer.record(timeMs, TimeUnit.MILLISECONDS);
32 | }
33 |
34 | public double getAvg() {
35 | if (count == 0) {
36 | return 0.0;
37 | }
38 | return (double) totalTime / count;
39 | }
40 |
41 | public void reset() {
42 | count = 0;
43 | totalTime = 0;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/JCPPHashUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util;
8 |
9 | import com.google.common.hash.HashFunction;
10 | import com.google.common.hash.Hashing;
11 |
12 | import java.nio.charset.StandardCharsets;
13 | import java.util.UUID;
14 |
15 | /**
16 | * @author baigod
17 | */
18 | public class JCPPHashUtil {
19 | public static HashFunction forName(String name) {
20 | return switch (name) {
21 | case "murmur3_32" -> Hashing.murmur3_32_fixed();
22 | case "murmur3_128" -> Hashing.murmur3_128();
23 | case "sha256" -> Hashing.sha256();
24 | default -> throw new IllegalArgumentException("Can't find hash function with name " + name);
25 | };
26 | }
27 |
28 | public static int hash(HashFunction hashFunction, String key) {
29 | return hashFunction.hashString(key, StandardCharsets.UTF_8).asInt();
30 | }
31 |
32 | public static int hash(HashFunction hashFunction, UUID key) {
33 | return hashFunction.hashString(key.toString(), StandardCharsets.UTF_8).asInt();
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/JCPPPair.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util;
8 |
9 | import lombok.AllArgsConstructor;
10 | import lombok.Data;
11 |
12 | @Data
13 | @AllArgsConstructor
14 | public class JCPPPair {
15 | private S first;
16 | private T second;
17 |
18 | public static JCPPPair of(S first, T second) {
19 | return new JCPPPair<>(first, second);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/annotation/AfterStartUp.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.annotation;
8 |
9 | import org.springframework.boot.context.event.ApplicationReadyEvent;
10 | import org.springframework.context.event.EventListener;
11 | import org.springframework.core.annotation.AliasFor;
12 | import org.springframework.core.annotation.Order;
13 |
14 | import java.lang.annotation.ElementType;
15 | import java.lang.annotation.Retention;
16 | import java.lang.annotation.RetentionPolicy;
17 | import java.lang.annotation.Target;
18 |
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Target(ElementType.METHOD)
21 | @EventListener(ApplicationReadyEvent.class)
22 | @Order
23 | public @interface AfterStartUp {
24 |
25 | int DISCOVERY_SERVICE = 1;
26 | int REGULAR_SERVICE = 2;
27 |
28 | @AliasFor(annotation = Order.class, attribute = "value")
29 | int order();
30 | }
31 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/annotation/AppComponent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.annotation;
8 |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
10 | import org.springframework.stereotype.Component;
11 |
12 | import java.lang.annotation.ElementType;
13 | import java.lang.annotation.Retention;
14 | import java.lang.annotation.RetentionPolicy;
15 | import java.lang.annotation.Target;
16 |
17 | /**
18 | * @author baigod
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target(ElementType.TYPE)
22 | @ConditionalOnExpression("'${service.type:null}'=='monolith' || '${service.type:null}'=='app'")
23 | @Component
24 | public @interface AppComponent {
25 |
26 |
27 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/annotation/ProtocolComponent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.annotation;
8 |
9 | import org.springframework.context.annotation.Condition;
10 | import org.springframework.context.annotation.ConditionContext;
11 | import org.springframework.context.annotation.Conditional;
12 | import org.springframework.core.annotation.AliasFor;
13 | import org.springframework.core.type.AnnotatedTypeMetadata;
14 | import org.springframework.stereotype.Component;
15 | import sanbing.jcpp.infrastructure.util.annotation.ProtocolComponent.ProtocolCondition;
16 |
17 | import java.lang.annotation.ElementType;
18 | import java.lang.annotation.Retention;
19 | import java.lang.annotation.RetentionPolicy;
20 | import java.lang.annotation.Target;
21 |
22 | /**
23 | * @author baigod
24 | */
25 | @Retention(RetentionPolicy.RUNTIME)
26 | @Target(ElementType.TYPE)
27 | @Conditional(ProtocolCondition.class)
28 | @Component
29 | public @interface ProtocolComponent {
30 |
31 | @AliasFor(annotation = Component.class)
32 | String value() default "";
33 |
34 | class ProtocolCondition implements Condition {
35 |
36 | @Override
37 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
38 | if (!metadata.isAnnotated(ProtocolComponent.class.getName())) {
39 | return true;
40 | }
41 |
42 | String serviceType = context.getEnvironment().getProperty("service.type", "null");
43 |
44 | String protocolName = (String) metadata.getAnnotationAttributes(ProtocolComponent.class.getName()).get("value");
45 |
46 | String enabled = context.getEnvironment().getProperty("service.protocols." + protocolName + ".enabled", "false");
47 |
48 | return ("monolith".equals(serviceType) || "protocol".equals(serviceType)) && "true".equals(enabled);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/async/JCPPExecutors.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.async;
8 |
9 | import java.util.concurrent.ExecutorService;
10 | import java.util.concurrent.Executors;
11 | import java.util.concurrent.ForkJoinPool;
12 |
13 | public class JCPPExecutors {
14 |
15 | public static ExecutorService newWorkStealingPool(int parallelism, String namePrefix) {
16 | return new ForkJoinPool(parallelism,
17 | new JCPPForkJoinWorkerThreadFactory(namePrefix),
18 | null, true);
19 | }
20 |
21 | public static ExecutorService newWorkStealingPool(int parallelism, Class> clazz) {
22 | return newWorkStealingPool(parallelism, clazz.getSimpleName());
23 | }
24 |
25 | public static ExecutorService newVirtualThreadPool(String namePrefix) {
26 | return Executors.newThreadPerTaskExecutor(new JCPPVirtualThreadFactory(namePrefix));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/async/JCPPForkJoinWorkerThreadFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.async;
8 |
9 | import lombok.NonNull;
10 | import lombok.ToString;
11 |
12 | import java.util.concurrent.ForkJoinPool;
13 | import java.util.concurrent.ForkJoinWorkerThread;
14 | import java.util.concurrent.atomic.AtomicLong;
15 |
16 | @ToString
17 | public class JCPPForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory {
18 | private final String namePrefix;
19 | private final AtomicLong threadNumber = new AtomicLong(1);
20 |
21 | public JCPPForkJoinWorkerThreadFactory(@NonNull String namePrefix) {
22 | this.namePrefix = namePrefix;
23 | }
24 |
25 | @Override
26 | public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
27 | ForkJoinWorkerThread thread = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
28 | thread.setContextClassLoader(this.getClass().getClassLoader());
29 | thread.setName(namePrefix + "-" + thread.getPoolIndex() + "-" + threadNumber.getAndIncrement());
30 | return thread;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/async/JCPPThreadFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.async;
8 |
9 | import com.google.common.util.concurrent.ThreadFactoryBuilder;
10 |
11 | import java.util.concurrent.ThreadFactory;
12 |
13 | public class JCPPThreadFactory {
14 | public static final String THREAD_TOPIC_SEPARATOR = " | ";
15 |
16 | public static ThreadFactory forName(String name) {
17 | return new ThreadFactoryBuilder()
18 | .setNameFormat(name)
19 | .setDaemon(true)
20 | .setPriority(Thread.NORM_PRIORITY)
21 | .build();
22 | }
23 |
24 | public static ThreadFactory forName(String name, int priority) {
25 | return new ThreadFactoryBuilder()
26 | .setNameFormat(name)
27 | .setDaemon(true)
28 | .setPriority(priority)
29 | .build();
30 | }
31 | public static void updateCurrentThreadName(String threadSuffix) {
32 | String name = Thread.currentThread().getName();
33 | int spliteratorIndex = name.indexOf(THREAD_TOPIC_SEPARATOR);
34 | if (spliteratorIndex > 0) {
35 | name = name.substring(0, spliteratorIndex);
36 | }
37 | name = name + THREAD_TOPIC_SEPARATOR + threadSuffix;
38 | Thread.currentThread().setName(name);
39 | }
40 |
41 | public static void addThreadNamePrefix(String prefix) {
42 | String name = Thread.currentThread().getName();
43 | name = prefix + "-" + name;
44 | Thread.currentThread().setName(name);
45 | }
46 |
47 |
48 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/async/JCPPVirtualThreadFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.async;
8 |
9 | import java.util.concurrent.ThreadFactory;
10 | import java.util.concurrent.atomic.AtomicLong;
11 |
12 | public class JCPPVirtualThreadFactory implements ThreadFactory {
13 | private final String namePrefix;
14 | private final AtomicLong threadNumber = new AtomicLong(1);
15 |
16 | public JCPPVirtualThreadFactory(String namePrefix) {
17 | this.namePrefix = namePrefix;
18 | }
19 |
20 | @Override
21 | public Thread newThread(Runnable r) {
22 | return Thread.ofVirtual().name(namePrefix + "-" + threadNumber.getAndIncrement()).unstarted(r);
23 | }
24 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/config/ScheduledTaskConfig.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.config;
8 |
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.scheduling.TaskScheduler;
12 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
13 |
14 | @Configuration
15 | public class ScheduledTaskConfig {
16 |
17 | @Bean
18 | public TaskScheduler taskScheduler() {
19 | ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
20 | scheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
21 | scheduler.setThreadNamePrefix("scheduled-task-");
22 | scheduler.initialize();
23 | return scheduler;
24 | }
25 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/config/ThreadPoolConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.config;
8 |
9 | import jakarta.annotation.PreDestroy;
10 | import org.springframework.context.annotation.Configuration;
11 | import sanbing.jcpp.infrastructure.util.async.JCPPExecutors;
12 | import sanbing.jcpp.infrastructure.util.async.JCPPThreadFactory;
13 |
14 | import java.util.concurrent.ExecutorService;
15 | import java.util.concurrent.Executors;
16 | import java.util.concurrent.ScheduledExecutorService;
17 | import java.util.concurrent.TimeUnit;
18 |
19 | /**
20 | * @author baigod
21 | */
22 | @Configuration
23 | public class ThreadPoolConfiguration {
24 |
25 | public static final ExecutorService JCPP_COMMON_THREAD_POOL = JCPPExecutors.newVirtualThreadPool("jcpp-common-virtual");
26 |
27 | public static final ScheduledExecutorService PROTOCOL_SESSION_SCHEDULED = Executors.newSingleThreadScheduledExecutor(JCPPThreadFactory.forName("protocol-session-schedule"));
28 |
29 | @PreDestroy
30 | public void destroy() {
31 | PROTOCOL_SESSION_SCHEDULED.shutdownNow();
32 |
33 | JCPP_COMMON_THREAD_POOL.shutdown();
34 |
35 | try {
36 | if (!JCPP_COMMON_THREAD_POOL.awaitTermination(5, TimeUnit.SECONDS)) {
37 | JCPP_COMMON_THREAD_POOL.shutdownNow();
38 | }
39 | } catch (InterruptedException e) {
40 | JCPP_COMMON_THREAD_POOL.shutdownNow();
41 | Thread.currentThread().interrupt();
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/exception/DataValidationException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.exception;
8 |
9 | public class DataValidationException extends RuntimeException {
10 |
11 | public DataValidationException(String message) {
12 | super(message);
13 | }
14 |
15 | public DataValidationException(String message, Throwable cause) {
16 | super(message, cause);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/exception/DownlinkException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.exception;
8 |
9 | /**
10 | * @author baigod
11 | */
12 | public class DownlinkException extends RuntimeException {
13 |
14 | public DownlinkException(String message) {
15 | super(message);
16 | }
17 |
18 | public DownlinkException(String message, Throwable cause) {
19 | super(message, cause);
20 | }
21 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/exception/IncorrectParameterException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.exception;
8 |
9 |
10 | public class IncorrectParameterException extends RuntimeException {
11 |
12 | public IncorrectParameterException(String message) {
13 | super(message);
14 | }
15 |
16 | public IncorrectParameterException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/BigNumberSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.SerializerProvider;
11 | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
12 | import com.fasterxml.jackson.databind.ser.std.NumberSerializer;
13 |
14 | import java.io.IOException;
15 |
16 | @JacksonStdImpl
17 | public class BigNumberSerializer extends NumberSerializer {
18 |
19 | private static final long JS_NUM_MAX = 9007199254740992L;
20 | private static final long JS_NUM_MIN = -9007199254740992L;
21 | public static final BigNumberSerializer instance = new BigNumberSerializer(Number.class);
22 |
23 | public BigNumberSerializer(Class extends Number> rawType) {
24 | super(rawType);
25 | }
26 |
27 | @Override
28 | public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
29 | long longValue = value.longValue();
30 | if (longValue >= JS_NUM_MIN && longValue <= JS_NUM_MAX) {
31 | super.serialize(value, gen, provider);
32 | } else {
33 | gen.writeString(value.toString());
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/DateDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.JsonDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalDateTime;
15 | import java.time.ZoneOffset;
16 | import java.time.format.DateTimeFormatter;
17 | import java.util.Date;
18 |
19 | /**
20 | * 时间反序列化
21 | *
22 | * @author baigod
23 | */
24 | public class DateDeserializer extends JsonDeserializer {
25 | public static final DateDeserializer INSTANCE = new DateDeserializer();
26 | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
27 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
28 |
29 | private DateDeserializer() {
30 | }
31 |
32 | @Override
33 | public Date deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
34 | String dateString = p.getText();
35 |
36 | return dateString.length() > 19
37 | ? Date.from(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER_MS).atZone(ZoneOffset.systemDefault()).toInstant())
38 | : Date.from(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER).atZone(ZoneOffset.systemDefault()).toInstant());
39 | }
40 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/DateSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.SerializerProvider;
11 | import com.fasterxml.jackson.databind.ser.std.StdSerializer;
12 | import org.apache.commons.lang3.time.FastDateFormat;
13 |
14 | import java.io.IOException;
15 | import java.util.Date;
16 |
17 | /**
18 | * 时间序列化
19 | *
20 | * @author baigod
21 | */
22 | public class DateSerializer extends StdSerializer {
23 | public static final DateSerializer INSTANCE = new DateSerializer();
24 | private static final FastDateFormat FAST_DATE_FORMAT_MS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
25 |
26 | private DateSerializer() {
27 | super(Date.class);
28 | }
29 |
30 | @Override
31 | public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
32 | gen.writeString(FAST_DATE_FORMAT_MS.format(value));
33 | }
34 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/InstantDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 |
10 | import com.fasterxml.jackson.core.JsonParser;
11 | import com.fasterxml.jackson.databind.DeserializationContext;
12 | import lombok.SneakyThrows;
13 | import org.apache.commons.lang3.time.FastDateFormat;
14 |
15 | import java.time.Instant;
16 | import java.time.format.DateTimeFormatter;
17 |
18 | /**
19 | * Instant 反序列化
20 | *
21 | * @author baigod
22 | */
23 | public class InstantDeserializer extends com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer {
24 | public static final InstantDeserializer INSTANCE = new InstantDeserializer();
25 |
26 | private final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
27 | private final FastDateFormat FAST_DATE_FORMAT_MS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
28 |
29 | private InstantDeserializer() {
30 | super(InstantDeserializer.INSTANT, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
31 | }
32 |
33 | @SneakyThrows
34 | @Override
35 | public Instant deserialize(JsonParser parser, DeserializationContext context) {
36 | String timestamp = parser.getText();
37 |
38 | return timestamp.length() > 19
39 | ? FAST_DATE_FORMAT_MS.parse(timestamp).toInstant()
40 | : FAST_DATE_FORMAT.parse(timestamp).toInstant();
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/InstantSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import java.time.format.DateTimeFormatter;
10 |
11 | /**
12 | * Instant 序列化
13 | *
14 | * @author baigod
15 | */
16 | public class InstantSerializer extends com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer {
17 | public static final InstantSerializer INSTANCE = new InstantSerializer();
18 |
19 | private InstantSerializer() {
20 | super(com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer.INSTANCE, true,false, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/LocalDateTimeDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalDateTime;
15 | import java.time.format.DateTimeFormatter;
16 |
17 | /**
18 | * LocalDateTime类型反序列化
19 | * 需要用到的字段上加 @JsonDeserialize(using = LocalDateTimeDeserializer.class)
20 | */
21 | public class LocalDateTimeDeserializer extends StdDeserializer {
22 | public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer();
23 |
24 | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
25 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
26 |
27 | private LocalDateTimeDeserializer() {
28 | super(LocalDateTime.class);
29 | }
30 |
31 | @Override
32 | public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext context)
33 | throws IOException {
34 |
35 | String dateString = jsonParser.getText();
36 | return dateString.length() > 19
37 | ? LocalDateTime.parse(dateString, DATE_TIME_FORMATTER_MS)
38 | : LocalDateTime.parse(dateString, DATE_TIME_FORMATTER);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/LocalDateTimeSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.JsonSerializer;
11 | import com.fasterxml.jackson.databind.SerializerProvider;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalDateTime;
15 | import java.time.format.DateTimeFormatter;
16 |
17 | /**
18 | * 时间类型序列化工具
19 | *
20 | * @author baigod
21 | */
22 | public class LocalDateTimeSerializer extends JsonSerializer {
23 | public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer();
24 |
25 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
26 |
27 | private LocalDateTimeSerializer() {
28 | }
29 |
30 | @Override
31 | public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
32 | gen.writeString(value.format(DATE_TIME_FORMATTER_MS));
33 | }
34 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/LocalTimeDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalDateTime;
15 | import java.time.LocalTime;
16 | import java.time.format.DateTimeFormatter;
17 |
18 | /**
19 | * LocalDateTime类型反序列化
20 | * 需要用到的字段上加 @JsonDeserialize(using = EnergyLocalTimeDeserializer.class)
21 | */
22 | public class LocalTimeDeserializer extends StdDeserializer {
23 | public static final LocalTimeDeserializer INSTANCE = new LocalTimeDeserializer();
24 |
25 | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
26 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
27 |
28 |
29 | private LocalTimeDeserializer() {
30 | super(LocalDateTime.class);
31 | }
32 |
33 | @Override
34 | public LocalTime deserialize(JsonParser jsonParser, DeserializationContext context)
35 | throws IOException {
36 |
37 | String dateString = jsonParser.getText();
38 | return dateString.length() > 8
39 | ? LocalTime.parse(dateString, DATE_TIME_FORMATTER_MS)
40 | : LocalTime.parse(dateString, DATE_TIME_FORMATTER);
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/LocalTimeSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.JsonSerializer;
11 | import com.fasterxml.jackson.databind.SerializerProvider;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalTime;
15 | import java.time.format.DateTimeFormatter;
16 |
17 | /**
18 | * 时间类型序列化工具
19 | *
20 | * @author baigod
21 | */
22 | public class LocalTimeSerializer extends JsonSerializer {
23 | public static final LocalTimeSerializer INSTANCE = new LocalTimeSerializer();
24 |
25 | private LocalTimeSerializer() {
26 | }
27 |
28 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
29 |
30 | @Override
31 | public void serialize(LocalTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
32 | gen.writeString(value.format(DATE_TIME_FORMATTER_MS));
33 | }
34 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/LongTimestampDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.JsonDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.time.LocalDateTime;
15 | import java.time.ZoneId;
16 |
17 | /**
18 | * 13位时间戳反序列化器
19 | * @author baigod
20 | */
21 | public class LongTimestampDeserializer extends JsonDeserializer {
22 |
23 | @Override
24 | public Long deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
25 |
26 | // 判定是否是long类型
27 | if ("LONG".equals(jsonParser.getNumberType().name())) {
28 | return jsonParser.getLongValue();
29 | }
30 | LocalDateTime localDateTime = LocalDateTime.parse(jsonParser.getValueAsString().replace(" ", "T").replace("Z", ""));
31 | ZoneId systemDefaultZone = ZoneId.systemDefault();
32 | return localDateTime.atZone(systemDefaultZone).toInstant().toEpochMilli();
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/SqlDateDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.JsonDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.sql.Date;
15 | import java.time.LocalDateTime;
16 | import java.time.ZoneOffset;
17 | import java.time.format.DateTimeFormatter;
18 |
19 | /**
20 | * sqlDate 反序列化
21 | *
22 | * @author baigod
23 | */
24 | public class SqlDateDeserializer extends JsonDeserializer {
25 |
26 | public static final SqlDateDeserializer INSTANCE = new SqlDateDeserializer();
27 | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
28 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
29 |
30 | private SqlDateDeserializer() {
31 | }
32 |
33 | @Override
34 | public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
35 | String dateString = p.getText();
36 |
37 | return dateString.length() > 19
38 | ? new Date(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER_MS).atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli())
39 | : new Date(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER).atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli());
40 | }
41 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/SqlDateSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.SerializerProvider;
11 | import com.fasterxml.jackson.databind.ser.std.StdSerializer;
12 | import org.apache.commons.lang3.time.FastDateFormat;
13 |
14 | import java.io.IOException;
15 | import java.sql.Date;
16 |
17 | /**
18 | * sqlDate序列化
19 | *
20 | * @author baigod
21 | */
22 | public class SqlDateSerializer extends StdSerializer {
23 | public static final SqlDateSerializer INSTANCE = new SqlDateSerializer();
24 |
25 | private static final FastDateFormat FAST_DATE_FORMAT_MS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
26 |
27 | private SqlDateSerializer() {
28 | super(Date.class);
29 | }
30 |
31 | @Override
32 | public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
33 | gen.writeString(FAST_DATE_FORMAT_MS.format(value));
34 | }
35 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/TimestampDeserializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonParser;
10 | import com.fasterxml.jackson.databind.DeserializationContext;
11 | import com.fasterxml.jackson.databind.JsonDeserializer;
12 |
13 | import java.io.IOException;
14 | import java.sql.Timestamp;
15 | import java.time.LocalDateTime;
16 | import java.time.ZoneOffset;
17 | import java.time.format.DateTimeFormatter;
18 |
19 | /**
20 | * timestamp 反序列化
21 | * @author baigod
22 | */
23 | public class TimestampDeserializer extends JsonDeserializer {
24 |
25 | public static final TimestampDeserializer INSTANCE = new TimestampDeserializer();
26 | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
27 | private static final DateTimeFormatter DATE_TIME_FORMATTER_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
28 |
29 | private TimestampDeserializer() {
30 | }
31 |
32 | @Override
33 | public Timestamp deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
34 | String dateString = p.getText();
35 |
36 | return dateString.length() > 19
37 | ? Timestamp.from(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER_MS).atZone(ZoneOffset.systemDefault()).toInstant())
38 | : Timestamp.from(LocalDateTime.parse(dateString, DATE_TIME_FORMATTER).atZone(ZoneOffset.systemDefault()).toInstant());
39 | }
40 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/jackson/TimestampSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.jackson;
8 |
9 | import com.fasterxml.jackson.core.JsonGenerator;
10 | import com.fasterxml.jackson.databind.SerializerProvider;
11 | import com.fasterxml.jackson.databind.ser.std.StdSerializer;
12 | import org.apache.commons.lang3.time.FastDateFormat;
13 |
14 | import java.io.IOException;
15 | import java.sql.Timestamp;
16 |
17 | /**
18 | * timestamp 序列化
19 | *
20 | * @author baigod
21 | */
22 | public class TimestampSerializer extends StdSerializer {
23 | public static final TimestampSerializer INSTANCE = new TimestampSerializer();
24 |
25 | private static final FastDateFormat FAST_DATE_FORMAT_MS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
26 |
27 | private TimestampSerializer() {
28 | super(Timestamp.class);
29 | }
30 |
31 | @Override
32 | public void serialize(Timestamp value, JsonGenerator gen, SerializerProvider provider) throws IOException {
33 | gen.writeString(FAST_DATE_FORMAT_MS.format(value));
34 | }
35 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/mdc/MDCUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.mdc;
8 |
9 | import org.apache.commons.lang3.StringUtils;
10 | import org.slf4j.MDC;
11 | import sanbing.jcpp.infrastructure.util.trace.Tracer;
12 | import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
13 |
14 |
15 | public class MDCUtils {
16 |
17 | private static final String TRACE_ID = "TRACE_ID";
18 |
19 | public static String putIfAbsentTracer() {
20 | String traceId = MDC.get(TRACE_ID);
21 |
22 | if (StringUtils.isEmpty(traceId)) {
23 | return recordTracer();
24 | }
25 |
26 | return traceId;
27 | }
28 |
29 | public static String recordTracer() {
30 | Tracer tracer = TracerContextUtil.getCurrentTracer();
31 |
32 | if (!StringUtils.isEmpty(tracer.getTraceId())) {
33 | MDC.put(TRACE_ID, tracer.getTraceId());
34 | } else {
35 | MDC.remove(TRACE_ID);
36 | }
37 |
38 | return tracer.getTraceId();
39 | }
40 |
41 | public static void cleanTracer() {
42 | MDC.remove(TRACE_ID);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/JCPPProperty.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.property;
8 |
9 | import lombok.Data;
10 |
11 | @Data
12 | public class JCPPProperty {
13 |
14 | private String key;
15 | private String value;
16 | }
17 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/PropertyUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.property;
8 |
9 |
10 | import org.apache.commons.lang3.StringUtils;
11 |
12 | import java.util.HashMap;
13 | import java.util.Map;
14 | import java.util.function.Function;
15 |
16 | public class PropertyUtils {
17 |
18 | public static Map getProps(String properties) {
19 | Map configs = new HashMap<>();
20 | if (StringUtils.isNotEmpty(properties)) {
21 | for (String property : properties.split(";")) {
22 | if (StringUtils.isNotEmpty(property)) {
23 | int delimiterPosition = property.indexOf(":");
24 | String key = property.substring(0, delimiterPosition);
25 | String value = property.substring(delimiterPosition + 1);
26 | configs.put(key, value);
27 | }
28 | }
29 | }
30 | return configs;
31 | }
32 |
33 | public static Map getProps(Map defaultProperties, String propertiesStr) {
34 | return getProps(defaultProperties, propertiesStr, PropertyUtils::getProps);
35 | }
36 |
37 | public static Map getProps(Map defaultProperties, String propertiesStr, Function> parser) {
38 | Map properties = defaultProperties;
39 | if (StringUtils.isNotBlank(propertiesStr)) {
40 | properties = new HashMap<>(properties);
41 | properties.putAll(parser.apply(propertiesStr));
42 | }
43 | return properties;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/trace/Tracer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.trace;
8 |
9 | import lombok.Data;
10 |
11 | import java.io.Serializable;
12 |
13 | @Data
14 | public class Tracer implements Serializable {
15 |
16 | private String traceId;
17 |
18 | private String origin;
19 |
20 | private final long tracerTs;
21 |
22 | public Tracer(String traceId, String origin) {
23 | this.traceId = traceId;
24 | this.origin = origin;
25 | this.tracerTs = System.currentTimeMillis();
26 | }
27 |
28 | public Tracer(String traceId, String origin, long tracerTs) {
29 | this.traceId = traceId;
30 | this.origin = origin;
31 | this.tracerTs = tracerTs;
32 | }
33 |
34 | public Tracer(String traceId, long tracerTs) {
35 | this.traceId = traceId;
36 | this.origin = "JCPP";
37 | this.tracerTs = tracerTs;
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/trace/TracerCallable.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.trace;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.util.mdc.MDCUtils;
11 |
12 | import java.util.concurrent.Callable;
13 |
14 | public class TracerCallable implements Callable {
15 |
16 | private Tracer tracer;
17 | private final Callable callable;
18 |
19 | public TracerCallable(Callable callable) {
20 | this.tracer = TracerContextUtil.getCurrentTracer();
21 | this.callable = callable;
22 | }
23 |
24 | @Override
25 | public T call() throws Exception {
26 | try {
27 | if (this.tracer != null) {
28 | TracerContextUtil.newTracer(tracer.getTraceId(), tracer.getOrigin(), tracer.getTracerTs());
29 |
30 | MDCUtils.recordTracer();
31 | }
32 |
33 | return this.callable.call();
34 | } finally {
35 | TracerContextUtil.cleanTracer();
36 |
37 | MDCUtils.cleanTracer();
38 |
39 | this.tracer = null;
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/trace/TracerRunnable.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.trace;
8 |
9 |
10 | import sanbing.jcpp.infrastructure.util.mdc.MDCUtils;
11 |
12 | public class TracerRunnable implements Runnable {
13 |
14 | private Tracer tracer;
15 | private final Runnable runnable;
16 |
17 | public TracerRunnable(Runnable runnable) {
18 | this.tracer = TracerContextUtil.getCurrentTracer();
19 | this.runnable = runnable;
20 | }
21 |
22 | @Override
23 | public void run() {
24 | try {
25 | if (this.tracer != null) {
26 | TracerContextUtil.newTracer(tracer.getTraceId(), tracer.getOrigin(), tracer.getTracerTs());
27 |
28 | MDCUtils.recordTracer();
29 | }
30 |
31 | this.runnable.run();
32 | } finally {
33 | TracerContextUtil.cleanTracer();
34 |
35 | MDCUtils.cleanTracer();
36 |
37 | this.tracer = null;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/validation/Length.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.validation;
8 |
9 | import jakarta.validation.Constraint;
10 | import jakarta.validation.Payload;
11 |
12 | import java.lang.annotation.ElementType;
13 | import java.lang.annotation.Retention;
14 | import java.lang.annotation.RetentionPolicy;
15 | import java.lang.annotation.Target;
16 |
17 | @Retention(RetentionPolicy.RUNTIME)
18 | @Target({ElementType.FIELD, ElementType.METHOD})
19 | @Constraint(validatedBy = {})
20 | public @interface Length {
21 | String message() default "length must be equal or less than {max}";
22 |
23 | String fieldName() default "";
24 |
25 | int max() default 255;
26 |
27 | Class>[] groups() default {};
28 |
29 | Class extends Payload>[] payload() default {};
30 | }
31 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/validation/StringLengthValidator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.validation;
8 |
9 | import com.fasterxml.jackson.databind.JsonNode;
10 | import jakarta.validation.ConstraintValidator;
11 | import jakarta.validation.ConstraintValidatorContext;
12 | import lombok.extern.slf4j.Slf4j;
13 | import org.apache.commons.lang3.StringUtils;
14 |
15 | @Slf4j
16 | public class StringLengthValidator implements ConstraintValidator {
17 | private int max;
18 |
19 | @Override
20 | public boolean isValid(Object value, ConstraintValidatorContext context) {
21 | String stringValue;
22 | if (value instanceof CharSequence || value instanceof JsonNode) {
23 | stringValue = value.toString();
24 | } else {
25 | return true;
26 | }
27 | if (StringUtils.isEmpty(stringValue)) {
28 | return true;
29 | }
30 | return stringValue.length() <= max;
31 | }
32 |
33 | @Override
34 | public void initialize(Length constraintAnnotation) {
35 | this.max = constraintAnnotation.max();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/validation/Validator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.validation;
8 |
9 | import sanbing.jcpp.infrastructure.util.exception.IncorrectParameterException;
10 |
11 | import java.util.UUID;
12 | import java.util.function.Function;
13 |
14 | public class Validator {
15 |
16 | public static void validateString(String val, String errorMessage) {
17 | if (val == null || val.isEmpty()) {
18 | throw new IncorrectParameterException(errorMessage);
19 | }
20 | }
21 |
22 | public static void validateString(String val, Function errorMessageFunction) {
23 | if (val == null || val.isEmpty()) {
24 | throw new IncorrectParameterException(errorMessageFunction.apply(val));
25 | }
26 | }
27 |
28 | public static void validatePositiveNumber(long val, String errorMessage) {
29 | if (val <= 0) {
30 | throw new IncorrectParameterException(errorMessage);
31 | }
32 | }
33 |
34 | public static void validateId(UUID id, Function errorMessageFunction) {
35 | if (id == null) {
36 | throw new IncorrectParameterException(errorMessageFunction.apply(id));
37 | }
38 | }
39 |
40 | public static void checkNotNull(Object reference, String errorMessage) {
41 | if (reference == null) {
42 | throw new IncorrectParameterException(errorMessage);
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/test/java/sanbing/jcpp/infrastructure/util/async/JCPPExecutorsTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.async;
8 |
9 | import org.junit.jupiter.api.Test;
10 | import org.slf4j.MDC;
11 | import sanbing.jcpp.infrastructure.util.mdc.MDCUtils;
12 | import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
13 | import sanbing.jcpp.infrastructure.util.trace.TracerRunnable;
14 |
15 | import java.util.concurrent.ExecutorService;
16 |
17 | class JCPPExecutorsTest {
18 |
19 | @Test
20 | void newVirtualThreadPool() {
21 | ExecutorService executorService = JCPPExecutors.newVirtualThreadPool("test-consumer-virtual");
22 |
23 | TracerContextUtil.newTracer();
24 | MDCUtils.recordTracer();
25 |
26 | System.out.println(MDC.get("TRACE_ID"));
27 |
28 | executorService.submit(new TracerRunnable(() -> {
29 | System.out.println(MDC.get("TRACE_ID"));
30 | }));
31 | }
32 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/test/java/sanbing/jcpp/infrastructure/util/codec/BCDUtilTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.codec;
8 |
9 | import cn.hutool.core.util.HexUtil;
10 | import org.junit.jupiter.api.Test;
11 |
12 | import static org.junit.jupiter.api.Assertions.assertArrayEquals;
13 |
14 | class BCDUtilTest {
15 |
16 | @Test
17 | void toBytesTest() {
18 | String pileCodeHex = "20231212000010";
19 |
20 | byte[] bytes = HexUtil.decodeHex(pileCodeHex);
21 |
22 | String pileCode = BCDUtil.toString(bytes);
23 |
24 | assert pileCodeHex.equals(pileCode);
25 |
26 | byte[] pileCodeBytes = BCDUtil.toBytes(pileCodeHex);
27 |
28 | assertArrayEquals(pileCodeBytes, bytes);
29 | }
30 | }
--------------------------------------------------------------------------------
/jcpp-infrastructure-util/src/test/java/sanbing/jcpp/infrastructure/util/codec/CP56Time2aUtilTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.infrastructure.util.codec;
8 |
9 | import cn.hutool.core.util.HexUtil;
10 | import org.junit.jupiter.api.Test;
11 |
12 | import java.time.LocalDateTime;
13 | import java.time.ZoneId;
14 | import java.util.Arrays;
15 |
16 | class CP56Time2aUtilTest {
17 |
18 | @Test
19 | void encodeTest() {
20 | LocalDateTime time = LocalDateTime.of(2025, 1, 22, 14, 30, 45, 123_000_000);
21 |
22 | byte[] bytes = CP56Time2aUtil.encode(time);
23 |
24 | System.out.println(Arrays.toString(bytes));
25 | System.out.println(HexUtil.encodeHex(bytes));
26 | System.out.println(time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
27 |
28 | LocalDateTime decode = CP56Time2aUtil.decode(bytes);
29 | System.out.println(decode.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
30 |
31 | assert time.equals(decode);
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
13 |
14 | sanbing
15 | jcpp-parent
16 | 1.0.0-SNAPSHOT
17 | ../pom.xml
18 |
19 | 4.0.0
20 |
21 | jcpp-protocol-api
22 | jar
23 | JChargePointProtocol Protocol Api Module
24 | 协议API
25 |
26 |
27 | ${basedir}/..
28 |
29 |
30 |
31 |
32 | sanbing
33 | jcpp-infrastructure-util
34 |
35 |
36 | sanbing
37 | jcpp-infrastructure-queue
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-reactor-netty
42 |
43 |
44 | com.github.ben-manes.caffeine
45 | caffeine
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/config/TracerInterceptor.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.adapter.config;
8 |
9 | import jakarta.servlet.http.HttpServletRequest;
10 | import jakarta.servlet.http.HttpServletResponse;
11 | import org.springframework.stereotype.Component;
12 | import org.springframework.web.servlet.HandlerInterceptor;
13 | import sanbing.jcpp.infrastructure.util.mdc.MDCUtils;
14 | import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
15 |
16 | import static sanbing.jcpp.infrastructure.util.trace.TracerContextUtil.*;
17 |
18 | @Component
19 | public class TracerInterceptor implements HandlerInterceptor {
20 |
21 | @Override
22 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
23 | String tracerId = request.getHeader(JCPP_TRACER_ID);
24 | String tracerOrigin = request.getHeader(JCPP_TRACER_ORIGIN);
25 | String tracerTsStr = request.getHeader(JCPP_TRACER_TS);
26 |
27 | long tracerTs;
28 | if (tracerTsStr != null) {
29 | try {
30 | tracerTs = Long.parseLong(tracerTsStr);
31 | } catch (NumberFormatException e) {
32 | tracerTs = System.currentTimeMillis();
33 | }
34 | } else {
35 | tracerTs = System.currentTimeMillis();
36 | }
37 |
38 | TracerContextUtil.newTracer(tracerId, tracerOrigin, tracerTs);
39 | MDCUtils.recordTracer();
40 |
41 | return true;
42 | }
43 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/config/UndertowServletWebServerCustomizer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.adapter.config;
8 |
9 | import io.undertow.server.DefaultByteBufferPool;
10 | import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
11 | import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
12 | import org.springframework.boot.web.server.WebServerFactoryCustomizer;
13 | import org.springframework.stereotype.Component;
14 |
15 |
16 | @Component
17 | public class UndertowServletWebServerCustomizer implements WebServerFactoryCustomizer {
18 | @Override
19 | public void customize(UndertowServletWebServerFactory factory) {
20 | factory.addDeploymentInfoCustomizers(deploymentInfo -> {
21 | WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
22 | webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 128 * 1024 * 1024));
23 | deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/config/WebMvcConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.adapter.config;
8 |
9 | import jakarta.annotation.Resource;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.http.converter.HttpMessageConverter;
12 | import org.springframework.http.converter.StringHttpMessageConverter;
13 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
14 | import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
15 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
16 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
17 |
18 | import java.nio.charset.StandardCharsets;
19 | import java.util.List;
20 |
21 | @Configuration
22 | public class WebMvcConfiguration implements WebMvcConfigurer {
23 |
24 | @Resource
25 | private TracerInterceptor tracerInterceptor;
26 |
27 | @Override
28 | public void configureMessageConverters(List> converters) {
29 | for (HttpMessageConverter> converter : converters) {
30 | if (converter instanceof StringHttpMessageConverter) {
31 | ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
32 | }
33 |
34 | if (converter instanceof MappingJackson2HttpMessageConverter) {
35 | ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
36 | }
37 | }
38 |
39 | // protobuf 序列化
40 | converters.add( new ProtobufHttpMessageConverter());
41 | }
42 |
43 | @Override
44 | public void addInterceptors(InterceptorRegistry registry) {
45 | registry.addInterceptor(tracerInterceptor).addPathPatterns("/**");
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/ForwarderCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import jakarta.validation.Valid;
10 | import jakarta.validation.constraints.NotNull;
11 | import lombok.Getter;
12 | import lombok.Setter;
13 | import sanbing.jcpp.protocol.cfg.enums.ForwarderType;
14 |
15 | @Setter
16 | @Getter
17 | public class ForwarderCfg {
18 |
19 | @NotNull
20 | private ForwarderType type;
21 |
22 | private MemoryCfg memory;
23 |
24 | @Valid
25 | private KafkaCfg kafka;
26 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/KafkaCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import lombok.Getter;
10 | import lombok.Setter;
11 | import sanbing.jcpp.infrastructure.util.property.PropertyUtils;
12 |
13 | import java.util.Map;
14 |
15 | @Getter
16 | @Setter
17 | public class KafkaCfg {
18 |
19 | private String topic;
20 |
21 | private boolean jcppPartition;
22 |
23 | private String bootstrapServers;
24 |
25 | private String acks;
26 |
27 | private EncoderType encoder;
28 |
29 | private int retries;
30 |
31 | private String compressionType; // none, gzip, snappy, lz4, zstd
32 |
33 | private int batchSize;
34 |
35 | private int lingerMs;
36 |
37 | private long bufferMemory;
38 |
39 | private Map otherProperties; // Other inline properties if necessary
40 |
41 | private String topicProperties;
42 |
43 | public void setOtherProperties(String otherProperties) {
44 | this.otherProperties = PropertyUtils.getProps(otherProperties);
45 | }
46 |
47 | public enum EncoderType {
48 | protobuf,
49 | json
50 | }
51 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/ListenerCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import jakarta.validation.Valid;
10 | import lombok.Getter;
11 | import lombok.Setter;
12 |
13 | @Getter
14 | @Setter
15 | public class ListenerCfg {
16 |
17 | @Valid
18 | private TcpCfg tcp;
19 | }
20 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/MemoryCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import lombok.Getter;
10 | import lombok.Setter;
11 |
12 | /**
13 | * @author baigod
14 | */
15 | @Getter
16 | @Setter
17 | public class MemoryCfg {
18 |
19 | private String topic;
20 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/ProtocolCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import jakarta.validation.Valid;
10 | import jakarta.validation.constraints.NotNull;
11 | import lombok.Getter;
12 | import lombok.Setter;
13 |
14 | @Getter
15 | @Setter
16 | public class ProtocolCfg {
17 |
18 | private boolean enabled;
19 |
20 | @NotNull
21 | @Valid
22 | private ListenerCfg listener;
23 |
24 | @NotNull
25 | @Valid
26 | private ForwarderCfg forwarder;
27 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/TcpCfg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg;
8 |
9 | import jakarta.validation.Valid;
10 | import jakarta.validation.constraints.Max;
11 | import jakarta.validation.constraints.Min;
12 | import lombok.Getter;
13 | import lombok.Setter;
14 |
15 | @Getter
16 | @Setter
17 | public class TcpCfg {
18 |
19 | private String bindAddress;
20 |
21 | @Max(65000)
22 | private int bindPort;
23 |
24 | @Min(1)
25 | private int bossGroupThreadCount;
26 |
27 | @Min(1)
28 | private int workerGroupThreadCount;
29 |
30 | private boolean soKeepAlive;
31 |
32 | @Min(1)
33 | @Max(65500)
34 | private int soBacklog;
35 |
36 | @Min(1)
37 | private int soRcvbuf;
38 |
39 | @Min(1)
40 | private int soSndbuf;
41 |
42 | private boolean nodelay;
43 |
44 | @Valid
45 | private TcpHandlerCfg handler;
46 |
47 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/enums/ForwarderType.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg.enums;
8 |
9 | public enum ForwarderType {
10 |
11 | memory, // 本地队列模式
12 |
13 | kafka // Kafka模式 - 发送到外部
14 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/cfg/enums/TcpHandlerType.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.cfg.enums;
8 |
9 | /**
10 | * @author baigod
11 | */
12 | public enum TcpHandlerType {
13 | TEXT,
14 | BINARY,
15 | JSON
16 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.domain;
8 |
9 | /**
10 | * @author baigod
11 | */
12 | public enum DownlinkCmdEnum {
13 |
14 | LOGIN_ACK,
15 |
16 | VERIFY_PRICING_ACK,
17 |
18 | QUERY_PRICING_ACK,
19 |
20 | SET_PRICING,
21 |
22 | REMOTE_START_CHARGING,
23 |
24 | TRANSACTION_RECORD,
25 |
26 | REMOTE_PARALLEL_START_CHARGING,
27 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ListenerToHandlerMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.domain;
8 |
9 | import java.util.UUID;
10 |
11 | public record ListenerToHandlerMsg(UUID id, byte[] msg, ProtocolSession session) {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolUplinkMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.domain;
8 |
9 | import io.netty.buffer.ByteBufUtil;
10 |
11 | import java.net.SocketAddress;
12 | import java.util.UUID;
13 |
14 | public record ProtocolUplinkMsg(SocketAddress address, UUID id, T data, int size) {
15 |
16 | @Override
17 | public String toString() {
18 | if (data instanceof byte[] bytes) {
19 | return ByteBufUtil.hexDump(bytes);
20 | } else {
21 | return data.toString();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/SessionCloseReason.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.domain;
8 |
9 | /**
10 | * @author baigod
11 | */
12 | public enum SessionCloseReason {
13 | /**
14 | * 自然销毁
15 | */
16 | DESTRUCTION,
17 |
18 | /**
19 | * 失活
20 | */
21 | INACTIVE,
22 |
23 | /**
24 | * 手动销毁
25 | */
26 | MANUALLY
27 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/SessionToHandlerMsg.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.domain;
8 |
9 | import sanbing.jcpp.proto.gen.ProtocolProto.DownlinkRequestMessage;
10 |
11 | /**
12 | * @author baigod
13 | */
14 | public record SessionToHandlerMsg(DownlinkRequestMessage downlinkMsg, ProtocolSession session) {
15 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/ChannelHandlerParameter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener;
8 |
9 | import io.micrometer.core.instrument.Timer;
10 | import sanbing.jcpp.infrastructure.stats.MessagesStats;
11 | import sanbing.jcpp.protocol.ProtocolMessageProcessor;
12 |
13 | import java.util.concurrent.atomic.AtomicInteger;
14 |
15 | public record ChannelHandlerParameter(String protocolName,
16 | ProtocolMessageProcessor protocolMessageProcessor,
17 | AtomicInteger connectionsGauge,
18 | MessagesStats uplinkMsgStats,
19 | MessagesStats downlinkMsgStats,
20 | Timer downlinkTimer) {
21 | }
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/configs/BinaryHandlerConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener.tcp.configs;
8 |
9 | import io.netty.handler.codec.ByteToMessageDecoder;
10 | import lombok.Data;
11 | import lombok.EqualsAndHashCode;
12 | import lombok.ToString;
13 | import sanbing.jcpp.protocol.cfg.enums.TcpHandlerType;
14 |
15 | import static sanbing.jcpp.protocol.cfg.enums.TcpHandlerType.BINARY;
16 |
17 | @Data
18 | @ToString
19 | @EqualsAndHashCode
20 | public class BinaryHandlerConfiguration implements HandlerConfiguration {
21 | public static final String LITTLE_ENDIAN_BYTE_ORDER = "LITTLE_ENDIAN";
22 |
23 | /**
24 | * 拆包器
25 | */
26 | private Class extends ByteToMessageDecoder> decoder;
27 |
28 | /**
29 | * 大小端(共用)
30 | */
31 | private String byteOrder;
32 |
33 | /**
34 | * 起始域HEX字符串
35 | */
36 | private String head;
37 |
38 | /**
39 | * 结束域(HeadTailFrameDecoder)
40 | */
41 | private String tail;
42 |
43 | /**
44 | * 最大帧长(LengthFieldBasedFrameDecoder)
45 | */
46 | private int maxFrameLength;
47 |
48 | /**
49 | * 长度域位置(共用)
50 | */
51 | private int lengthFieldOffset;
52 |
53 | /**
54 | * 长度域长度(共用)
55 | */
56 | private int lengthFieldLength;
57 |
58 | /**
59 | * 长度调整(共用)
60 | */
61 | private int lengthAdjustment;
62 |
63 | /**
64 | * 初始跳过字节数(共用)
65 | */
66 | private int initialBytesToStrip;
67 |
68 | /**
69 | * 快速失败(LengthFieldBasedFrameDecoder)
70 | */
71 | private boolean failFast;
72 |
73 | public TcpHandlerType getType() {
74 | return BINARY;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/configs/HandlerConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener.tcp.configs;
8 |
9 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
10 | import com.fasterxml.jackson.annotation.JsonSubTypes;
11 | import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
12 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
13 | import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
14 | import sanbing.jcpp.protocol.cfg.enums.TcpHandlerType;
15 |
16 | @JsonTypeInfo(
17 | use = Id.NAME,
18 | property = "type"
19 | )
20 | @JsonSubTypes({
21 | @Type(
22 | value = TextHandlerConfiguration.class,
23 | name = "TEXT"
24 | ),
25 | @Type(
26 | value = BinaryHandlerConfiguration.class,
27 | name = "BINARY"
28 | ),
29 | @Type(
30 | value = JsonHandlerConfiguration.class,
31 | name = "JSON"
32 | )
33 | })
34 | @JsonIgnoreProperties(
35 | ignoreUnknown = true
36 | )
37 | public interface HandlerConfiguration {
38 | TcpHandlerType getType();
39 | }
40 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/configs/JsonHandlerConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener.tcp.configs;
8 |
9 | import lombok.Data;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.ToString;
12 | import sanbing.jcpp.protocol.cfg.enums.TcpHandlerType;
13 |
14 | import static sanbing.jcpp.protocol.cfg.enums.TcpHandlerType.JSON;
15 |
16 | @Data
17 | @ToString
18 | @EqualsAndHashCode
19 | public class JsonHandlerConfiguration implements HandlerConfiguration {
20 | public TcpHandlerType getType() {
21 | return JSON;
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/configs/TextHandlerConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener.tcp.configs;
8 |
9 | import lombok.Data;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.ToString;
12 | import sanbing.jcpp.protocol.cfg.enums.TcpHandlerType;
13 |
14 | import static sanbing.jcpp.protocol.cfg.enums.TcpHandlerType.TEXT;
15 |
16 | @Data
17 | @ToString
18 | @EqualsAndHashCode
19 | public class TextHandlerConfiguration implements HandlerConfiguration {
20 | public static final String SYSTEM_LINE_SEPARATOR = "SYSTEM_LINE_SEPARATOR";
21 |
22 | private int maxFrameLength;
23 |
24 | private boolean stripDelimiter;
25 |
26 | private String messageSeparator;
27 |
28 | private String charsetName;
29 |
30 | public TcpHandlerType getType() {
31 | return TEXT;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/decoder/TcpMsgDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 开源代码,仅供学习和交流研究使用,商用请联系三丙
3 | * 微信:mohan_88888
4 | * 抖音:程序员三丙
5 | * 付费课程知识星球:https://t.zsxq.com/aKtXo
6 | */
7 | package sanbing.jcpp.protocol.listener.tcp.decoder;
8 |
9 | import com.fasterxml.jackson.databind.JsonNode;
10 | import io.netty.buffer.ByteBuf;
11 | import io.netty.channel.ChannelHandlerContext;
12 | import io.netty.handler.codec.MessageToMessageDecoder;
13 | import lombok.RequiredArgsConstructor;
14 | import lombok.extern.slf4j.Slf4j;
15 | import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
16 | import sanbing.jcpp.protocol.domain.ProtocolUplinkMsg;
17 |
18 | import java.nio.charset.Charset;
19 | import java.util.List;
20 | import java.util.UUID;
21 | import java.util.function.Function;
22 |
23 | @RequiredArgsConstructor
24 | @Slf4j
25 | public class TcpMsgDecoder extends MessageToMessageDecoder {
26 | private final String protocolName;
27 | private final Function transformer;
28 |
29 | @Override
30 | public void decode(ChannelHandlerContext ctx, ByteBuf msg, List