云快充1.5.0 初始化

This commit is contained in:
3god
2024-10-08 09:38:54 +08:00
parent dea6774942
commit cb19b45919
297 changed files with 18020 additions and 28 deletions

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
抖音关注:程序员三丙
知识星球https://t.zsxq.com/j9b21
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>sanbing</groupId>
<artifactId>jcpp-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jcpp-app-bootstrap</artifactId>
<packaging>jar</packaging>
<name>JChargePointProtocol Application Bootstrap Module</name>
<description>App引导程序</description>
<properties>
<main.dir>${basedir}/..</main.dir>
<disruptor.version>3.4.4</disruptor.version>
</properties>
<dependencies>
<dependency>
<groupId>sanbing</groupId>
<artifactId>jcpp-app</artifactId>
</dependency>
<dependency>
<groupId>sanbing</groupId>
<artifactId>jcpp-protocol-yunkuaichong</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>application</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<layout>ZIP</layout>
<mainClass>sanbing.jcpp.JCPPServerApplication</mainClass>
<excludeDevtools>true</excludeDevtools>
<layers>
<enabled>true</enabled>
<configuration>${project.basedir}/src/layers.xml</configuration>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
抖音关注:程序员三丙
知识星球https://t.zsxq.com/j9b21
-->
<layers xmlns="http://www.springframework.org/schema/boot/layers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
https://www.springframework.org/schema/boot/layers/layers-2.7.xsd">
<application>
<into layer="spring-boot-loader">
<include>org/springframework/boot/loader/**</include>
</into>
<into layer="application" />
</application>
<dependencies>
<into layer="application">
<includeModuleDependencies />
</into>
<into layer="snapshot-dependencies">
<include>*:*:*SNAPSHOT</include>
</into>
<into layer="dependencies" />
</dependencies>
<layerOrder>
<layer>dependencies</layer>
<layer>spring-boot-loader</layer>
<layer>snapshot-dependencies</layer>
<layer>application</layer>
</layerOrder>
</layers>

View File

@@ -0,0 +1,39 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp;
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays;
/**
* @author baigod
*/
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class JCPPServerApplication {
private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name";
private static final String DEFAULT_SPRING_CONFIG_PARAM = SPRING_CONFIG_NAME_KEY + "=" + "app-service";
public static void main(String[] args) {
new SpringApplicationBuilder(JCPPServerApplication.class).bannerMode(Banner.Mode.LOG).run(updateArguments(args));
}
private static String[] updateArguments(String[] args) {
if (Arrays.stream(args).noneMatch(arg -> arg.startsWith(SPRING_CONFIG_NAME_KEY))) {
String[] modifiedArgs = new String[args.length + 1];
System.arraycopy(args, 0, modifiedArgs, 0, args.length);
modifiedArgs[args.length] = DEFAULT_SPRING_CONFIG_PARAM;
return modifiedArgs;
}
return args;
}
}

View File

@@ -0,0 +1,214 @@
server:
address: "${HTTP_BIND_ADDRESS:0.0.0.0}"
port: "${HTTP_BIND_PORT:8080}"
undertow:
buffer-size: "${SERVER_UNDERTOW_BUFFER_SIZE:16384}"
directBuffers: "${SERVER_UNDERTOW_DIRECT_BUFFERS:true}"
threads:
io: "${SERVER_UNDERTOW_THREADS_IO:4}"
worker: "${SERVER_UNDERTOW_THREADS_WORKER:128}"
max-http-post-size: "${SERVER_UNDERTOW_MAX_HTTP_POST_SIZE:10MB}"
no-request-timeout: "${SERVER_UNDERTOW_NO_REQUEST_TIMEOUT:10000}"
accesslog:
enabled: true
pattern: "%t %a %r %s (%D ms)"
dir: /var/log/sanbing/accesslog
options:
server:
record-request-start-time: true
spring:
application:
name: "${SPRING_APPLICATION_NAME:java-charge-point-server}"
datasource:
driver-class-name: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}"
url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://10.102.12.102:30135/jcpp}"
username: "${SPRING_DATASOURCE_USERNAME:postgres}"
password: "${SPRING_DATASOURCE_PASSWORD:postgres}"
hikari:
leak-detection-threshold: "${SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}"
maximum-pool-size: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}"
register-mbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}"
mybatis-plus:
type-handlers-package: sanbing.jcpp.app.dal.config.ibatis.typehandlers
management:
endpoints:
web:
exposure:
include: '${METRICS_ENDPOINTS_EXPOSE:prometheus,health}'
endpoint:
health:
show-details: always
metrics:
enabled: "${METRICS_ENABLED:true}"
timer:
percentiles: "${METRICS_TIMER_PERCENTILES:0.5}"
# 应用程序服务注册中心配置
zk:
enabled: "${ZOOKEEPER_ENABLED:true}"
url: "${ZOOKEEPER_URL:zookeeper:2181}"
retry-interval-ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}"
connection-timeout-ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}"
session-timeout-ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}"
zk-dir: "${ZOOKEEPER_NODES_DIR:/jcpp}"
recalculate-delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}"
# 队列配置
queue:
# 可选 kafka、memory
type: "${QUEUE_TYPE:memory}"
partitions:
hash_function_name: "${QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" # murmur3_32, murmur3_128 or sha256
in_memory:
stats:
print-interval-ms: "${QUEUE_IN_MEMORY_STATS_PRINT_INTERVAL_MS:60000}"
kafka:
bootstrap-servers: "${KAFKA_SERVERS:kafka:9092}"
ssl:
enabled: "${KAFKA_SSL_ENABLED:false}"
truststore-location: "${KAFKA_SSL_TRUSTSTORE_LOCATION:}"
truststore-password: "${KAFKA_SSL_TRUSTSTORE_PASSWORD:}"
keystore-location: "${KAFKA_SSL_KEYSTORE_LOCATION:}"
keystore-password: "${KAFKA_SSL_KEYSTORE_PASSWORD:}"
key-password: "${KAFKA_SSL_KEY_PASSWORD:}"
acks: "${KAFKA_ACKS:1}"
retries: "${KAFKA_RETRIES:1}"
compression-type: "${KAFKA_COMPRESSION_TYPE:lz4}" # none, gzip, snappy, lz4, zstd
batch-size: "${KAFKA_BATCH_SIZE:1048576}"
linger-ms: "${KAFKA_LINGER_MS:1}"
max-request-size: "${KAFKA_MAX_REQUEST_SIZE:1048576}"
max-in-flight-requests-per-connection: "${KAFKA_MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION:5}"
buffer-memory: "${BUFFER_MEMORY:33554432}"
replication-factor: "${QUEUE_KAFKA_REPLICATION_FACTOR:1}"
max-poll-interval-ms: "${QUEUE_KAFKA_MAX_POLL_INTERVAL_MS:300000}"
max-poll-records: "${QUEUE_KAFKA_MAX_POLL_RECORDS:10240}"
max-partition-fetch-bytes: "${QUEUE_KAFKA_MAX_PARTITION_FETCH_BYTES:16777216}"
fetch-max-bytes: "${QUEUE_KAFKA_FETCH_MAX_BYTES:134217728}"
request-timeout-ms: "${QUEUE_KAFKA_REQUEST_TIMEOUT_MS:30000}"
session-timeout-ms: "${QUEUE_KAFKA_SESSION_TIMEOUT_MS:10000}"
auto-offset-reset: "${QUEUE_KAFKA_AUTO_OFFSET_RESET:earliest}"
other-inline: "${QUEUE_KAFKA_OTHER_PROPERTIES:}"
topic-properties:
app: "${QUEUE_KAFKA_APP_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:52428800;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
consumer-stats:
enabled: "${QUEUE_KAFKA_CONSUMER_STATS_ENABLED:true}"
print-interval-ms: "${QUEUE_KAFKA_CONSUMER_STATS_MIN_PRINT_INTERVAL_MS:60000}"
kafka-response-timeout-ms: "${QUEUE_KAFKA_CONSUMER_STATS_RESPONSE_TIMEOUT_MS:1000}"
app:
topic: "${QUEUE_APP_TOPIC:protocol_uplink}"
poll-interval: "${QUEUE_APP_POLL_INTERVAL_MS:5}"
pack-processing-timeout: "${QUEUE_APP_PACK_PROCESSING_TIMEOUT_MS:2000}"
consumer-per-partition: "${QUEUE_APP_CONSUMER_PER_PARTITION:true}"
partitions: "${QUEUE_APP_PARTITIONS:10}"
# 可选 protobuf推荐、json需要跟..forwarder.kafka.encoder保持一致
decoder: "${QUEUE_APP_DECODER:protobuf}"
stats:
enabled: "${QUEUE_APP_STATS_ENABLED:true}"
print-interval-ms: "${QUEUE_APP_STATS_PRINT_INTERVAL_MS:60000}"
# 应用程序缓存配置
cache:
type: "${CACHE_TYPE:caffeine}" # caffeine or redis
specs:
piles:
timeToLiveInMinutes: "${CACHE_SPECS_PILES_TTL:15}"
maxSize: "${CACHE_SPECS_PILES_MAX_SIZE:1000}"
pileSessions:
timeToLiveInMinutes: "${CACHE_SPECS_PILE_SESSIONS_TTL:1440}"
maxSize: "${CACHE_SPECS_PILE_SESSIONS_MAX_SIZE:100000}"
redis:
connection:
type: "${REDIS_CONNECTION_TYPE:standalone}"
standalone:
host: "${REDIS_HOST:redis}"
port: "${REDIS_PORT:6379}"
useDefaultClientConfig: "${REDIS_USE_DEFAULT_CLIENT_CONFIG:true}"
clientName: "${REDIS_CLIENT_NAME:standalone}"
commandTimeout: "${REDIS_CLIENT_COMMAND_TIMEOUT:30000}"
shutdownTimeout: "${REDIS_CLIENT_SHUTDOWN_TIMEOUT:1000}"
readTimeout: "${REDIS_CLIENT_READ_TIMEOUT:60000}"
usePoolConfig: "${REDIS_CLIENT_USE_POOL_CONFIG:false}"
cluster:
nodes: "${REDIS_NODES:redis-node-0:6379,redis-node-1:6379,redis-node-2:6379,redis-node-3:6379,redis-node-4:6379,redis-node-5:6379}"
max-redirects: "${REDIS_MAX_REDIRECTS:12}"
useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:false}"
sentinel:
master: "${REDIS_MASTER:mymaster}"
sentinels: "${REDIS_SENTINELS:redis-sentinel:26379}"
password: "${REDIS_SENTINEL_PASSWORD:sanbing}"
useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:false}"
db: "${REDIS_DB:0}"
password: "${REDIS_PASSWORD:sanbing}"
pool_config:
maxTotal: "${REDIS_POOL_CONFIG_MAX_TOTAL:128}"
maxIdle: "${REDIS_POOL_CONFIG_MAX_IDLE:128}"
minIdle: "${REDIS_POOL_CONFIG_MIN_IDLE:16}"
testOnBorrow: "${REDIS_POOL_CONFIG_TEST_ON_BORROW:false}"
testOnReturn: "${REDIS_POOL_CONFIG_TEST_ON_RETURN:false}"
testWhileIdle: "${REDIS_POOL_CONFIG_TEST_WHILE_IDLE:true}"
minEvictableMs: "${REDIS_POOL_CONFIG_MIN_EVICTABLE_MS:60000}"
evictionRunsMs: "${REDIS_POOL_CONFIG_EVICTION_RUNS_MS:30000}"
maxWaitMills: "${REDIS_POOL_CONFIG_MAX_WAIT_MS:60000}"
numberTestsPerEvictionRun: "${REDIS_POOL_CONFIG_NUMBER_TESTS_PER_EVICTION_RUN:3}"
blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}"
evictTtlInMs: "${REDIS_EVICT_TTL_MS:60000}"
service:
# 服务类型:纯协议解析前置 - protocol纯应用后端 - app单体服务(包含protocol和app) - monolith
type: "${SERVICE_TYPE:monolith}"
# 可自定义的服务ID如果不指定则默认为HOSTNAME
id: "${SERVICE_ID:}"
protocols:
sessions:
default-inactivity-timeout-in-sec: "${PROTOCOLS_SESSIONS_DEFAULT_INACTIVITY_TIMEOUT_IN_SEC:600}"
default-state-check-interval-in-sec: "${PROTOCOLS_SESSIONS_DEFAULT_STATE_CHECK_INTERVAL_IN_SEC:60}"
yunkuaichongV150:
enabled: "${PROTOCOLS_YUNKUAICHONGV150_ENABLED:true}"
listener:
tcp:
bind-address: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_BIND_ADDRESS:0.0.0.0}"
bind-port: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_BIND_PORT:38001}"
boss-group-thread_count: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_BOSS_GROUP_THREADS:4}"
worker-group-thread-count: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_WORKER_GROUP_THREADS:16}"
so-keep-alive: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_SO_KEEPALIVE:true}"
so-backlog: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_SO_BACKLOG:128}"
so-rcvbuf: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_SO_RCVBUF:65536}"
so-sndbuf: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_SO_SNDBUF:65536}"
nodelay: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_NODELAY:true}"
handler:
idle-timeout-seconds: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_HANDLER_IDLE_TIMEOUT_SECONDS:600}"
max_connections: "${PROTOCOLS_YUNKUAICHONGV150_LISTENER_TCP_HANDLER_MAX_CONNECTIONS:100000}"
# 默认为二进制类型的拆包器
# 可选JSON类型的拆包器 "${PROTOCOLS_YUNKUAICHONGV150_NETTY_HANDLER_BINARY_CONFIGURATION:type:JSON}"
# 可选纯文本类型的拆包器 "${PROTOCOLS_YUNKUAICHONGV150_NETTY_HANDLER_BINARY_CONFIGURATION:type:TEXT;maxFrameLength:128;stripDelimiter:true;messageSeparator:null;charsetName:UTF-8}"
configuration: "${PROTOCOLS_YUNKUAICHONGV150_NETTY_HANDLER_BINARY_CONFIGURATION:type:BINARY;decoder:sanbing.jcpp.protocol.listener.tcp.decoder.JCPPLengthFieldBasedFrameDecoder;byteOrder:LITTLE_ENDIAN;head:68;lengthFieldOffset:1;lengthFieldLength:1;lengthAdjustment:2;initialBytesToStrip:0}"
forwarder:
# 如果是单体服务可选kafka、memory未来计划扩展RocketMQ, GRpc、REST
type: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_TYPE:memory}"
memory:
topic: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_MEMORY_TOPIC:protocol_uplink}"
kafka:
topic: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_TOPIC:protocol_uplink}"
jcpp-partition: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_JCPP_PARTITION:true}" # 是否利用JCPP的分片框架
# 以下配置只有在service.type为protocol时且jcpp-partition为false时才生效
bootstrap-servers: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_SERVERS:10.102.12.102:9092}"
acks: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_ACKS:1}"
# # 可选 protobuf推荐、json
encoder: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_ENCODER:protobuf}"
retries: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_RETRIES:1}"
compression-type: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_COMPRESSION_TYPE:lz4}" # none, gzip, snappy, lz4, zstd
batch-size: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_BATCH_SIZE:16384}"
linger-ms: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_KAFKA_LINGER_MS:0}"
buffer-memory: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_BUFFER_MEMORY:33554432}"
other-properties: "${PROTOCOLS_YUNKUAICHONGV150_FORWARD_QUEUE_KAFKA_OTHER_PROPERTIES:}"
thread-pool:
sharding:
hash_function_name: "${THREAD_POOL_SHARDING_HASH_FUNCTION_NAME:murmur3_128}" # murmur3_32, murmur3_128 or sha256
parallelism: "${THREAD_POOL_SHARDING_PARALLELISM:128}"
stats-print-interval-ms: "${THREAD_POOL_SHARDING_STATS_PRINT_INTERVAL_MS:10000}"

View File

@@ -0,0 +1,12 @@
___ ________ ________ ________
|\ \|\ ____\|\ __ \|\ __ \
\ \ \ \ \___|\ \ \|\ \ \ \|\ \
__ \ \ \ \ \ \ \ ____\ \ ____\
|\ \\_\ \ \ \____\ \ \___|\ \ \___|
\ \________\ \_______\ \__\ \ \__\
\|________|\|_______|\|__| \|__|
===================================================
:: ${application.title} :: ${application.formatted-version}
===================================================

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO" monitorInterval="30">
<properties>
<Property name="LOG_DIR">/var/log/sanbing/jcpp</Property>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} [%X{TRACE_ID}] [%t] %p %c{1} %m%n%throwable</Property>
</properties>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="ROLLING_FILE" fileName="${LOG_DIR}/jcpp-app.log"
filePattern="${LOG_DIR}/jcpp-app.%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${LOG_DIR}" maxDepth="1">
<IfFileName glob="*.log"/>
<IfAccumulatedFileSize exceeds="10GB"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<logger name="org.springframework" level="INFO" />
<AsyncRoot level="INFO" includeLocation="true">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="ROLLING_FILE"/>
</AsyncRoot>
<AsyncLogger name="sanbing.jcpp" level="INFO" additivity="false" includeLocation="false">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="ROLLING_FILE"/>
</AsyncLogger>
<AsyncLogger name="sanbing.jcpp.protocol" level="${env:PROTOCOLS_LOG_LEVEL:-TRACE}"
additivity="false" includeLocation="false">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="ROLLING_FILE"/>
</AsyncLogger>
</Loggers>
</configuration>

View File

@@ -0,0 +1,27 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestMethodOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
/**
* @author baigod
*/
@ActiveProfiles("test")
@SpringBootTest(classes = JCPPServerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AbstractTestBase {
static {
System.setProperty("spring.config.name", "app-service");
}
protected final Logger log = LoggerFactory.getLogger(this.getClass());
}

View File

@@ -0,0 +1,72 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.app.dal.mapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import sanbing.jcpp.AbstractTestBase;
import sanbing.jcpp.app.dal.config.ibatis.enums.GunOptStatusEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.GunRunStatusEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
import sanbing.jcpp.app.dal.entity.Gun;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.time.LocalDateTime;
import java.util.UUID;
import static sanbing.jcpp.app.dal.mapper.PileMapperTest.NORMAL_PILE_ID;
import static sanbing.jcpp.app.dal.mapper.StationMapperTest.NORMAL_STATION_ID;
import static sanbing.jcpp.app.dal.mapper.UserMapperTest.NORMAL_USER_ID;
/**
* @author baigod
*/
public class GunMapperTest extends AbstractTestBase {
static final UUID[] NORMAL_GUN_ID = new UUID[]{
UUID.fromString("8f1ffb5b-e536-4f2b-8cd0-31f7d0348a44"),
UUID.fromString("ae256617-b747-4110-b27a-00773e03bed1"),
UUID.fromString("d15dbb29-ea2f-4094-b448-dff853e9275f"),
UUID.fromString("b4a2de24-d7ff-4828-a0d8-2429a6253f9c"),
UUID.fromString("f505f7e2-9e1c-4251-8f7f-9a8eae84372a"),
UUID.fromString("0c5bab7b-786b-4e05-ab26-618c3f5a6086"),
UUID.fromString("2db4ad92-e353-4ac2-a2b0-942cb778eca6"),
UUID.fromString("203833e7-0a44-4f1c-935e-cd43e6dbbf46"),
UUID.fromString("3f3a61e9-de55-4177-9b4e-3a1d8c529890"),
UUID.fromString("cf1a8970-5aa9-4636-a76e-d6bcf98b4a07")
};
@Resource
GunMapper gunMapper;
@Test
void curdTest() {
gunMapper.delete(Wrappers.lambdaQuery());
for (int i = 0; i < NORMAL_PILE_ID.length; i++) {
UUID pileId = NORMAL_PILE_ID[i];
UUID gunId = NORMAL_GUN_ID[i];
Gun gun = Gun.builder()
.id(gunId)
.createdTime(LocalDateTime.now())
.additionalInfo(JacksonUtil.newObjectNode())
.gunNo("01")
.gunName("三丙的1号枪")
.gunCode("20231212000001-" + (i + 1))
.stationId(NORMAL_STATION_ID)
.pileId(pileId)
.ownerId(NORMAL_USER_ID)
.ownerType(OwnerTypeEnum.C)
.runStatus(GunRunStatusEnum.IDLE)
.runStatusUpdatedTime(LocalDateTime.now())
.optStatus(GunOptStatusEnum.AVAILABLE)
.build();
gunMapper.insertOrUpdate(gun);
log.info("{}", gunMapper.selectById(gunId));
}
}
}

View File

@@ -0,0 +1,66 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.app.dal.mapper;
import cn.hutool.core.math.Money;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
import sanbing.jcpp.AbstractTestBase;
import sanbing.jcpp.app.dal.config.ibatis.enums.OrderStatusEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.OrderTypeEnum;
import sanbing.jcpp.app.dal.entity.Order;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
import static sanbing.jcpp.app.dal.mapper.GunMapperTest.NORMAL_GUN_ID;
import static sanbing.jcpp.app.dal.mapper.PileMapperTest.NORMAL_PILE_ID;
import static sanbing.jcpp.app.dal.mapper.StationMapperTest.NORMAL_STATION_ID;
import static sanbing.jcpp.app.dal.mapper.UserMapperTest.NORMAL_USER_ID;
/**
* @author baigod
*/
public class OrderMapperTest extends AbstractTestBase {
@Resource
OrderMapper orderMapper;
@Test
void testOrderMapper() {
orderMapper.delete(Wrappers.lambdaQuery());
Order order = Order.builder()
.id(UUID.randomUUID())
.internalOrderNo(IdUtil.getSnowflake(1, 1).nextIdStr())
.externalOrderNo(IdUtil.getSnowflake(1, 1).nextIdStr())
.pileOrderNo(RandomStringUtils.randomNumeric(16))
.createdTime(LocalDateTime.now())
.additionalInfo(JacksonUtil.newObjectNode())
.updatedTime(LocalDateTime.now())
.cancelledTime(null)
.status(OrderStatusEnum.IN_CHARGING)
.type(OrderTypeEnum.CHARGE)
.creatorId(NORMAL_USER_ID)
.stationId(NORMAL_STATION_ID)
.pileId(NORMAL_PILE_ID[0])
.gunId(NORMAL_GUN_ID[0])
.plateNo("浙A88888")
.settlementAmount(new Money(100D).getCent())
.settlementDetails(JacksonUtil.newObjectNode())
.electricityQuantity(new BigDecimal("100"))
.build();
orderMapper.insertOrUpdate(order);
log.info("{}", orderMapper.selectById(order.getId()));
}
}

View File

@@ -0,0 +1,74 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.app.dal.mapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import sanbing.jcpp.AbstractTestBase;
import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.PileStatusEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.PileTypeEnum;
import sanbing.jcpp.app.dal.entity.Pile;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.UUID;
import static sanbing.jcpp.app.dal.mapper.StationMapperTest.NORMAL_STATION_ID;
import static sanbing.jcpp.app.dal.mapper.UserMapperTest.NORMAL_USER_ID;
/**
* @author baigod
*/
public class PileMapperTest extends AbstractTestBase {
static final UUID[] NORMAL_PILE_ID = new UUID[]{
UUID.fromString("fd7b3f60-db6c-4347-bff3-3c922985b95c"),
UUID.fromString("fa621927-6458-4e09-9666-99c52230db2b"),
UUID.fromString("afec0b0a-ad82-4923-97da-70e4a5d5e2c6"),
UUID.fromString("3e45ae30-2848-4d5a-a7b8-bd8504a6713d"),
UUID.fromString("349ff65e-ce8e-435a-928b-52fdef2828f2"),
UUID.fromString("e60d5b2d-8014-4f8f-b828-e207e6cf4a8f"),
UUID.fromString("8f010829-b505-4e57-8b93-6bdf981ac4e1"),
UUID.fromString("081842e2-9e74-4abb-aeab-b2cbfeb7a335"),
UUID.fromString("f04cf40a-0fbe-40f7-a07c-5b663ad68e98"),
UUID.fromString("ec522751-e1d3-4117-a887-3bdae7892369")
};
@Resource
PileMapper pileMapper;
@Test
void curdTest() {
pileMapper.delete(Wrappers.lambdaQuery());
for (int i = 0; i < 10; i++) {
UUID pileId = NORMAL_PILE_ID[i];
Pile pile = Pile.builder()
.id(pileId)
.createdTime(LocalDateTime.now())
.additionalInfo(JacksonUtil.newObjectNode())
.pileName(String.format("三丙家的%d号充电桩", i + 1))
.pileCode("202312120000" + new DecimalFormat("00").format(i + 1))
.protocol("yunkuaichongV150")
.stationId(NORMAL_STATION_ID)
.ownerId(NORMAL_USER_ID)
.ownerType(OwnerTypeEnum.C)
.brand("星星")
.model("10A")
.manufacturer("星星")
.status(PileStatusEnum.IDLE)
.type(PileTypeEnum.AC)
.build();
pileMapper.insertOrUpdate(pile);
log.info("{}", pileMapper.selectById(pileId));
}
}
}

View File

@@ -0,0 +1,55 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.app.dal.mapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import sanbing.jcpp.AbstractTestBase;
import sanbing.jcpp.app.dal.config.ibatis.enums.OwnerTypeEnum;
import sanbing.jcpp.app.dal.config.ibatis.enums.StationStatusEnum;
import sanbing.jcpp.app.dal.entity.Station;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.time.LocalDateTime;
import java.util.UUID;
import static sanbing.jcpp.app.dal.mapper.UserMapperTest.NORMAL_USER_ID;
/**
* @author baigod
*/
class StationMapperTest extends AbstractTestBase {
static final UUID NORMAL_STATION_ID = UUID.fromString("07d80c81-fe99-4a1f-a6aa-dc4d798b5626");
@Resource
StationMapper stationMapper;
@Test
void curdTest() {
stationMapper.delete(Wrappers.lambdaQuery());
Station station = Station.builder()
.id(NORMAL_STATION_ID)
.createdTime(LocalDateTime.now())
.additionalInfo(JacksonUtil.newObjectNode())
.stationName("三丙家专属充电站")
.stationCode("S20241001001")
.ownerId(NORMAL_USER_ID)
.longitude(120.107936F)
.latitude(30.267014F)
.ownerType(OwnerTypeEnum.C)
.province("浙江省")
.city("杭州市")
.county("西湖区")
.address("西溪路552-1号")
.status(StationStatusEnum.OPERATIONAL)
.build();
stationMapper.insertOrUpdate(station);
log.info("{}", stationMapper.selectById(NORMAL_STATION_ID));
}
}

View File

@@ -0,0 +1,44 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.app.dal.mapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import sanbing.jcpp.AbstractTestBase;
import sanbing.jcpp.app.dal.config.ibatis.enums.UserStatusEnum;
import sanbing.jcpp.app.dal.entity.User;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* @author baigod
*/
class UserMapperTest extends AbstractTestBase {
static final UUID NORMAL_USER_ID = UUID.fromString("21cbf909-a23a-4396-840a-f34061f59f95");
@Resource
private UserMapper userMapper;
@Test
void curdTest() {
userMapper.delete(Wrappers.lambdaQuery());
User user = User.builder()
.id(NORMAL_USER_ID)
.createdTime(LocalDateTime.now())
.additionalInfo(JacksonUtil.newObjectNode())
.status(UserStatusEnum.ENABLE)
.userName("sanbing")
.userCredentials(JacksonUtil.newObjectNode())
.build();
userMapper.insertOrUpdate(user);
log.info("{}", userMapper.selectById(NORMAL_USER_ID));
}
}

View File

@@ -0,0 +1,98 @@
/**
* 抖音关注:程序员三丙
* 知识星球https://t.zsxq.com/j9b21
*/
package sanbing.jcpp.infrastructure.cache;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.data.redis.core.*;
import sanbing.jcpp.AbstractTestBase;
import java.time.Duration;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;
class RedisCacheConfigurationTest extends AbstractTestBase {
@Resource
RedisTemplate<String, Object> redisTemplate;
@Resource
ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
final static int testTimes = 10_000;
final static String hashKey = "hashKey";
@Test
@Order(1)
void kvTest() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
IntStream.range(0, testTimes).forEach(i -> {
String key = "field:" + i;
String value = "value:" + i;
valueOperations.set(key, value, Duration.ofMinutes(1));
});
Object o = valueOperations.get("field:1000");
System.out.println(Objects.requireNonNull(o).getClass() + " : " + o);
}
@Test
@Order(2)
void hashTest() {
HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
IntStream.range(0, testTimes).forEach(i -> {
String key = "field:" + i;
String value = "value:" + i;
hashOperations.put(hashKey, key, value);
});
redisTemplate.expire(hashKey, Duration.ofMinutes(1));
Map<Object, Object> slowKey = hashOperations.entries(hashKey);
System.out.println("map size:" + slowKey.size());
}
@Test
@Order(3)
void reactiveKVTest() {
ReactiveValueOperations<String, Object> valueOperations = reactiveRedisTemplate.opsForValue();
IntStream.range(0, testTimes).forEach(i -> {
String key = "field:" + i;
String value = "value:" + i;
valueOperations.set(key, value, Duration.ofMinutes(1)).block();
});
Object o = valueOperations.get("field:1000").block();
System.out.println(Objects.requireNonNull(o).getClass() + " : " + o);
}
@Test
@Order(4)
void reactiveHashTest() throws InterruptedException {
ReactiveHashOperations<String, Object, Object> hashOperations = reactiveRedisTemplate.opsForHash();
IntStream.range(0, testTimes).forEach(i -> {
String key = "field:" + i;
String value = "value:" + i;
hashOperations.put(hashKey, key, value).block();
});
redisTemplate.expire(hashKey, Duration.ofMinutes(1));
CountDownLatch latch = new CountDownLatch(1);
hashOperations.entries(hashKey).collectList().subscribe(entries -> {
System.out.println("size:" + entries.size());
latch.countDown();
});
latch.await();
}
}

View File

@@ -0,0 +1,2 @@
redis.connection.type=cluster
redis.cluster.nodes=10.102.12.101:30700,10.102.12.101:32027,10.102.12.101:30767,10.102.12.101:30250,10.102.12.101:30612,10.102.12.101:32303