From 9742357d7624ce611894acce432ef72f37e2a825 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=AD=8F=E7=81=BF=E6=96=8C?= <15815221751@163.com>
Date: Wed, 19 Nov 2025 12:43:59 +0800
Subject: [PATCH] first commit
---
.gitignore | 38 +
.idea/.gitignore | 8 +
.idea/ApifoxUploaderProjectSetting.xml | 6 +
.idea/copilot.data.migration.agent.xml | 6 +
.idea/copilot.data.migration.ask.xml | 6 +
.idea/copilot.data.migration.ask2agent.xml | 6 +
.idea/copilot.data.migration.edit.xml | 6 +
.idea/encodings.xml | 22 +
.idea/misc.xml | 13 +
.idea/uiDesigner.xml | 124 ++
pom.xml | 96 ++
yuxingshi-ssm-common/pom.xml | 28 +
.../yuxingshi-ssm-core/pom.xml | 63 ++
.../common/core/constants/CacheConstants.java | 27 +
.../core/constants/CommonConstants.java | 23 +
.../ssm/common/core/constants/ResultCode.java | 180 +++
.../core/constants/SecurityConstants.java | 38 +
.../common/core/constants/TokenConstants.java | 29 +
.../common/core/domain/dto/BasePageDTO.java | 41 +
.../core/domain/dto/BasePageReqDTO.java | 32 +
.../common/core/domain/dto/LoginUserDTO.java | 54 +
.../ssm/common/core/domain/vo/R.java | 141 +++
.../ssm/common/core/utils/JsonUtil.java | 240 ++++
.../ssm/common/core/utils/ServletUtil.java | 157 +++
.../ssm/common/core/utils/StringUtil.java | 56 +
.../yuxingshi-ssm-intercepter/pom.xml | 38 +
.../common/intercepter/config/WebConfig.java | 22 +
.../intercepter/filer/AuthInterceptor.java | 37 +
...ot.autoconfigure.AutoConfiguration.imports | 2 +
.../yuxingshi-ssm-mybatisplus/pom.xml | 36 +
.../mybatisplus/config/MyBatisPlusConfig.java | 25 +
.../common/mybatisplus/domain/BaseEntity.java | 21 +
.../handler/MyMetaObjectHandler.java | 25 +
...ot.autoconfigure.AutoConfiguration.imports | 2 +
.../yuxingshi-ssm-redis/pom.xml | 45 +
.../ssm/common/redis/config/RedisConfig.java | 118 ++
.../ssm/common/redis/server/RedisService.java | 1002 +++++++++++++++++
...ot.autoconfigure.AutoConfiguration.imports | 2 +
.../yuxingshi-ssm-security/pom.xml | 53 +
.../common/security/annotation/ValueIn.java | 21 +
.../security/annotation/ValueInValidator.java | 57 +
.../ssm/common/security/dto/TokenDto.java | 28 +
.../common/security/service/TokenService.java | 171 +++
.../ssm/common/security/utils/JwtUtil.java | 156 +++
.../common/security/utils/SecurityUtil.java | 53 +
yuxingshi-ssm-server/pom.xml | 47 +
.../main/java/yuxingshi/ssm/server/Main.java | 7 +
.../src/main/resources/application.yaml | 0
48 files changed, 3408 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.gitignore
create mode 100644 .idea/ApifoxUploaderProjectSetting.xml
create mode 100644 .idea/copilot.data.migration.agent.xml
create mode 100644 .idea/copilot.data.migration.ask.xml
create mode 100644 .idea/copilot.data.migration.ask2agent.xml
create mode 100644 .idea/copilot.data.migration.edit.xml
create mode 100644 .idea/encodings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/uiDesigner.xml
create mode 100644 pom.xml
create mode 100644 yuxingshi-ssm-common/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CacheConstants.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CommonConstants.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/ResultCode.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/SecurityConstants.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/TokenConstants.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageDTO.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageReqDTO.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/LoginUserDTO.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/vo/R.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/JsonUtil.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/ServletUtil.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/StringUtil.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-intercepter/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/config/WebConfig.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/filer/AuthInterceptor.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/config/MyBatisPlusConfig.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/domain/BaseEntity.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/handler/MyMetaObjectHandler.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-redis/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/config/RedisConfig.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/server/RedisService.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/pom.xml
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/annotation/ValueIn.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/annotation/ValueInValidator.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/dto/TokenDto.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/service/TokenService.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/utils/JwtUtil.java
create mode 100644 yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java/yuxingshi/ssm/common/security/utils/SecurityUtil.java
create mode 100644 yuxingshi-ssm-server/pom.xml
create mode 100644 yuxingshi-ssm-server/src/main/java/yuxingshi/ssm/server/Main.java
create mode 100644 yuxingshi-ssm-server/src/main/resources/application.yaml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/ApifoxUploaderProjectSetting.xml b/.idea/ApifoxUploaderProjectSetting.xml
new file mode 100644
index 0000000..4c89849
--- /dev/null
+++ b/.idea/ApifoxUploaderProjectSetting.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml
new file mode 100644
index 0000000..4ea72a9
--- /dev/null
+++ b/.idea/copilot.data.migration.agent.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.ask.xml b/.idea/copilot.data.migration.ask.xml
new file mode 100644
index 0000000..7ef04e2
--- /dev/null
+++ b/.idea/copilot.data.migration.ask.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml
new file mode 100644
index 0000000..1f2ea11
--- /dev/null
+++ b/.idea/copilot.data.migration.ask2agent.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.edit.xml b/.idea/copilot.data.migration.edit.xml
new file mode 100644
index 0000000..8648f94
--- /dev/null
+++ b/.idea/copilot.data.migration.edit.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..970f226
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e8d124d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b30fa80
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,96 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm
+ 1.0-SNAPSHOT
+ pom
+
+ yuxingshi-ssm-server
+ yuxingshi-ssm-common
+
+
+
+ 17
+ 17
+ UTF-8
+
+ 3.3.3
+ 3.50.0
+ 3.5.7
+ 4.4
+ 2.0.0
+ 0.9.1
+ 2.3.0
+ 5.8.22
+ 2.14.4
+ 1.0.0
+
+ test
+ -Xmx256m
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ ${mybatis-plus.version}
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+ ${pagehelper.boot.version}
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jwt.version}
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb.version}
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
+ com.alibaba
+ transmittable-thread-local
+ ${transmittable-thread-local.version}
+
+
+
+ com.a3test.component
+ idworker-snowflake
+ ${idworker-snowflake.version}
+
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/pom.xml b/yuxingshi-ssm-common/pom.xml
new file mode 100644
index 0000000..bc17674
--- /dev/null
+++ b/yuxingshi-ssm-common/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm
+ 1.0-SNAPSHOT
+
+
+ yuxingshi-ssm-common
+ pom
+
+ yuxingshi-ssm-redis
+ yuxingshi-ssm-core
+ yuxingshi-ssm-mybatisplus
+ yuxingshi-ssm-security
+ yuxingshi-ssm-intercepter
+
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/pom.xml b/yuxingshi-ssm-common/yuxingshi-ssm-core/pom.xml
new file mode 100644
index 0000000..f436f60
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm-common
+ 1.0-SNAPSHOT
+
+
+ yuxingshi.ssm.common.core
+ yuxingshi-ssm-core
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+
+
+ org.springframework
+ spring-web
+
+
+ io.projectreactor
+ reactor-core
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CacheConstants.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CacheConstants.java
new file mode 100644
index 0000000..0703b63
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CacheConstants.java
@@ -0,0 +1,27 @@
+package yuxingshi.ssm.common.core.constants;
+
+/**
+ * 缓存常量
+ */
+public class CacheConstants {
+ /**
+ * 缓存分割符
+ */
+ public final static String CACHE_SPLIT_COLON = ":";
+
+
+ /**
+ * 登录用户缓存有效期,默认720(分钟)
+ */
+ public final static long LOGIN_USER_EXPIRATION = 720;
+
+ /**
+ * 缓存刷新时间,默认120(分钟)
+ */
+ public final static long REFRESH_TIME = 120;
+
+ /**
+ * 用户登录凭证有效期延期临界值
+ */
+ public static final long LOGIN_USER_EXP_CRITICAL_TIME = 120L;
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CommonConstants.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CommonConstants.java
new file mode 100644
index 0000000..8bc382d
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/CommonConstants.java
@@ -0,0 +1,23 @@
+package yuxingshi.ssm.common.core.constants;
+
+/**
+ * 通用常量
+ */
+public class CommonConstants {
+ /**
+ * 通用日期格式
+ */
+ public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ /**
+ * 默认编码
+ */
+ public final static String UTF8 = "UTF-8";
+ /**
+ * 默认分隔符
+ */
+ public final static String DEFAULT_DELIMITER = ", ";
+ /**
+ * 空字符串
+ */
+ public final static String EMPTY_STR = "";
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/ResultCode.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/ResultCode.java
new file mode 100644
index 0000000..44f562b
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/ResultCode.java
@@ -0,0 +1,180 @@
+package yuxingshi.ssm.common.core.constants;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum ResultCode {
+
+ //---------------------------2xx
+
+ /**
+ * 操作成功
+ */
+ SUCCESS (200000, "操作成功"),
+
+ //------------------------4xx
+ //400
+
+ /**
+ * 无效的参数
+ */
+ INVALID_PARA (400000, "无效的参数"),
+ /**
+ * 无效的验证码
+ */
+ INVALID_CODE (400001, "无效的验证码"),
+
+ /**
+ * 错误的验证码
+ */
+ ERROR_CODE (400002, "错误的验证码"),
+
+ /**
+ * 手机号格式错误
+ */
+ ERROR_PHONE_FORMAT (400003, "手机号格式错误"),
+
+ /**
+ * 超过每日发送次数限制
+ */
+ SEND_MSG_OVERLIMIT (400004, "超过每日发送次数限制"),
+
+ /**
+ * 无效的区划
+ */
+ INVALID_REGION (400005, "无效的区划"),
+
+ /**
+ * 参数类型不匹配
+ */
+ PARA_TYPE_MISMATCH (400006, "参数类型不匹配"),
+
+ /**
+ * 账号已停用,登录失败
+ */
+ USER_DISABLE (400007, "账号已停用,登录失败"),
+
+ /**
+ * 请求参数超过最大限制
+ */
+ INVALID_PARA_MAX_SIZE (4000008,"请求参数超过最大限制"),
+
+
+ /**
+ * 手机号已经被注册
+ */
+ PHONE_ALREADY_REGISTER (4000009,"手机号已经被注册"),
+
+
+ /**
+ * 用户不存在
+ */
+ USER_NOT_EXIST (4000010,"用户不存在"),
+
+
+ /**
+ * 解密失败
+ */
+ DECODE_FAIL (4000011,"解密失败"),
+
+
+ /**
+ * 用户身份不合法
+ */
+ USER_IDENTITY_ILLEGAL (4000012,"用户身份不合法"),
+
+
+ /**
+ * 用户状态不合法
+ */
+ USER_STATUS_ILLEGAL (4000013,"用户状态不合法"),
+
+
+
+
+ /**
+ * 密码格式不通过
+ */
+ PASSWORD_FORMAT_INVALID (4000015,"密码格式不通过"),
+
+
+ //401
+
+ /**
+ * 令牌不能为空
+ */
+ TOKEN_EMPTY (401000, "令牌不能为空"),
+
+ /**
+ * 令牌已过期或验证不正确!
+ */
+ TOKEN_INVALID (401001, "令牌已过期或验证不正确!"),
+
+ /**
+ * 令牌已过期!
+ */
+ TOKEN_OVERTIME (401002, "令牌已过期!"),
+
+ /**
+ * 登录状态已过期!
+ */
+ LOGIN_STATUS_OVERTIME (401003, "登录状态已过期!"),
+
+ /**
+ * 令牌验证失败!
+ */
+ TOKEN_CHECK_FAILED (401004, "令牌验证失败!"),
+
+ // 403
+ NOT_PERMISSION (403001,"您没有权限!"),
+
+ //404
+
+ /**
+ * 服务未找到!
+ */
+ SERVICE_NOT_FOUND (404000, "服务未找到"),
+
+ URL_NOT_FOUND (404001, "url未找到"),
+
+ //405
+
+ /**
+ * 请求方法不支持!
+ */
+ REQUEST_METNHOD_NOT_SUPPORTED (405000, "请求方法不支持"),
+
+
+ //---------------------5xx
+
+ /**
+ * 服务繁忙请稍后重试!
+ */
+ ERROR (500000, "服务繁忙请稍后重试"),
+
+ /**
+ * 操作失败
+ */
+ FAILED (500001, "操作失败"),
+
+
+
+
+ //---------------------枚举占位
+ /**
+ * 占位专用
+ */
+ RESERVED (99999999, "占位专用");
+
+ /**
+ * 响应码
+ */
+ private final int code;
+
+ /**
+ * 响应消息
+ */
+ private final String msg;
+}
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/SecurityConstants.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/SecurityConstants.java
new file mode 100644
index 0000000..367e241
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/SecurityConstants.java
@@ -0,0 +1,38 @@
+package yuxingshi.ssm.common.core.constants;
+
+/**
+ * 安全相关的常量类
+ */
+public class SecurityConstants {
+
+ /**
+ * 用户标识
+ */
+ public static final String USER_KEY = "user_key";
+
+ /**
+ * 用户ID
+ */
+ public static final String USER_ID = "user_id";
+
+ /**
+ * 用户来源
+ */
+ public static final String USER_FROM = "user_from";
+
+
+ /**
+ * 用户昵称
+ */
+ public static final String USERNAME = "username";
+
+
+ /**
+ * 用户身份
+ */
+ public static final String USER_IDENTITY = "user_identity";
+ /**
+ * 授权信息字段
+ */
+ public static final String AUTHENTICATION = "authorization";
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/TokenConstants.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/TokenConstants.java
new file mode 100644
index 0000000..be9f6f2
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/constants/TokenConstants.java
@@ -0,0 +1,29 @@
+package yuxingshi.ssm.common.core.constants;
+
+/**
+ * 存放token相关的常量
+ */
+public class TokenConstants {
+ /**
+ * 令牌密钥
+ */
+ public static final String SECRET = "jyuxingshiabcdefghijklmnopqrstuvwxyz";
+
+ /**
+ * 令牌前缀
+ */
+ public static final String PREFIX = "Bearer ";
+
+ /**
+ * 缓存的token key
+ */
+ public static final String LOGIN_TOKEN_KEY = "logintoken:";
+
+
+ /**
+ * 缓存信息分割符号
+ */
+
+ public static final String LOGIN_CACHE_INGO_SPLIT = "-";
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageDTO.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageDTO.java
new file mode 100644
index 0000000..1f36d6d
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageDTO.java
@@ -0,0 +1,41 @@
+package yuxingshi.ssm.common.core.domain.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 响应结果分页报文
+ */
+@Data
+public class BasePageDTO {
+ /**
+ * 查询结果总数
+ */
+ Integer totals;
+
+ /**
+ * 总页数
+ */
+ Integer totalPages;
+
+ /**
+ * 数据列表
+ */
+ List list;
+
+ /**
+ * 计算总页数
+ *
+ * @param totals 总数量
+ * @param pageSize 页大小
+ * @return 页数
+ */
+ public static int calculateTotalPages(long totals, int pageSize) {
+ if (pageSize <= 0) {
+ throw new IllegalArgumentException("Page size must be greater than 0.");
+ }
+ return (int) Math.ceil((double) totals / pageSize);
+ }
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageReqDTO.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageReqDTO.java
new file mode 100644
index 0000000..dadfac2
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/BasePageReqDTO.java
@@ -0,0 +1,32 @@
+package yuxingshi.ssm.common.core.domain.dto;
+
+import jakarta.validation.constraints.Max;
+import lombok.Data;
+
+/**
+ * 分页查询基类DTO
+ */
+@Data
+public class BasePageReqDTO {
+
+ /**
+ * 分页编码
+ */
+ private Integer pageNo = 1;
+
+ /**
+ * 分页数量
+ */
+ @Max(20)
+ private Integer pageSize = 10;
+
+ /**
+ * 获取偏移
+ *
+ * @return 偏移信息
+ */
+ public Integer getOffset() {
+ return (pageNo - 1) * pageSize;
+ }
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/LoginUserDTO.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/LoginUserDTO.java
new file mode 100644
index 0000000..76e7409
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/dto/LoginUserDTO.java
@@ -0,0 +1,54 @@
+package yuxingshi.ssm.common.core.domain.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 登录用户信息
+ */
+@Getter
+@Setter
+@ToString
+public class LoginUserDTO {
+ /**
+ * 用户标识
+ */
+ private String userKey;
+
+
+ /**
+ * 用户Id
+ */
+ private String userId;
+
+ /**
+ * 用户来源
+ */
+ private String userFrom;
+
+
+ /**
+ * 用户名
+ */
+ private String userName;
+
+
+ /**
+ * 用户身份
+ */
+ private Integer userIdentity;
+
+
+
+ /**
+ * 登录时间
+ */
+ private Long loginTime;
+
+
+ /**
+ * 过期时间
+ */
+ private Long expireTime;
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/vo/R.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/vo/R.java
new file mode 100644
index 0000000..498ff09
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/domain/vo/R.java
@@ -0,0 +1,141 @@
+package yuxingshi.ssm.common.core.domain.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import yuxingshi.ssm.common.core.constants.ResultCode;
+
+/**
+ * 响应报文封装
+ *
+ * @param 响应数据
+ */
+@Getter
+@Setter
+@ToString
+public class R {
+
+ /**
+ * 响应码
+ */
+ private int code;
+
+ /**
+ * 消息
+ */
+ private String msg;
+
+ /**
+ * 数据
+ */
+ private T data;
+
+ /**
+ * 成功响应
+ *
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R ok() {
+ return restResult(null, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
+ }
+
+ /**
+ * 成功响应
+ * @param data 响应数据
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R ok(T data) {
+ return restResult(data, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
+ }
+
+ /**
+ * 成功响应
+ * @param data 响应数据
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R ok(T data, String msg) {
+ return restResult(data, ResultCode.SUCCESS.getCode(), msg);
+ }
+
+ /**
+ * 失败响应
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail() {
+ return restResult(null, ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
+ }
+
+ /**
+ * 失败响应
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail(String msg) {
+ return restResult(null, ResultCode.ERROR.getCode(), msg);
+ }
+
+ /**
+ * 失败响应
+ * @param code 响应码
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail(Integer code,String msg) {
+ return restResult(null, code, msg);
+ }
+
+ /**
+ * 失败响应
+ * @param data 响应数据
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail(T data) {
+ return restResult(data, ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
+ }
+
+ /**
+ * 失败响应
+ * @param data 响应数据
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail(T data, String msg) {
+ return restResult(data, ResultCode.ERROR.getCode(), msg);
+ }
+
+ /**
+ * 失败响应
+ * @param code 响应编码
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ public static R fail(int code, String msg) {
+ return restResult(null, code, msg);
+ }
+
+ /**
+ * 响应结果
+ * @param data 响应数据
+ * @param code 响应编码
+ * @param msg 响应消息
+ * @return 响应报文
+ * @param 数据类型
+ */
+ private static R restResult(T data, int code, String msg) {
+ R apiResult = new R<>();
+ apiResult.setCode(code);
+ apiResult.setData(data);
+ apiResult.setMsg(msg);
+ return apiResult;
+ }
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/JsonUtil.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/JsonUtil.java
new file mode 100644
index 0000000..1ea7f9d
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/JsonUtil.java
@@ -0,0 +1,240 @@
+package yuxingshi.ssm.common.core.utils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import yuxingshi.ssm.common.core.constants.CommonConstants;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JSON工具类
+ * 提供:
+ * 1. 对象转JSON
+ * 2. JSON转对象
+ */
+@Slf4j
+public class JsonUtil {
+
+ /**
+ * 对象转换器
+ */
+ private static ObjectMapper OBJECT_MAPPER;
+
+ /**
+ * init...
+ * 1. .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ * 在反序列化时,当遇到 JSON 数据中存在 Java 对象对应类中没有定义的属性时,默认情况下
+ * Jackson 会抛出异常。通过将这个配置项设置为 false,表示允许在反序列化时忽略那些未知的属
+ * 性,不会因为出现额外的属性而导致反序列化失败,增强了对不同来源 JSON 数据的兼容性。
+ * 例如: Student:name, 如果传进来的JSON为Student:name,sex,但是sex并不存在,那么设置为false将忽略sex
+ *
+ * 2. .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
+ * 在序列化时,如果Java 对象中包含日期类型默认情况下 Jackson 可能会将日期转换为时间戳来表示。
+ * 将此配置设置为false,意味着不采用时间戳的方式来表示日期,而是会按照后续配置的其他日期相关格式进行序列化,
+ * 以便生成更具可读性的日期格式表示在 JSON 数据中。
+ *
+ * 3. .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ * 在序列化时,Java对象中没有任何属性值(为空),默认情况下 Jackson 可能会抛出异常。设置
+ * 此项为 false 后,允许对这样的空对象进行序列化,即便对象没有实质内容也能生成对应的 JSON
+ * 表示(通常可能是一个空的 JSON 对象 {}),避免了因对象为空导致序列化失败的情况。
+ *
+ * 4. .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
+ * 在反序列化时,如果 JSON 数据中指定的类型信息与期望的 Java 类型层次结构不匹配(例如类型
+ * 标识错误等情况),默认会抛出异常。将这个配置设为 false,可以放宽这种限制,使得在遇到类
+ * 型不太准确但仍有可能处理的情况下,尝试继续进行反序列化而不是直接失败,提高对可能存在错
+ * 误类型标识的 JSON 数据的容错性。
+ *
+ * 5. .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
+ * 在序列化时,如果 Java 对象中有以日期类型作为键(比如在 Map 中,键是 Date 类型等情况)的
+ * 结构,如果设置为true会将日期键转换为时间戳形式。设置为 false 则按照其他日期相关配置来处
+ * 理,保证日期键也以期望的格式进行序列化,使得整个 JSON 结构中日期相关内容都能保持统一的
+ * 格式呈现。(默认值为false)
+ *
+ * 6. .configure(MapperFeature.USE_ANNOTATIONS, false)
+ * Jackson 支持通过在 Java 类的属性或方法上添加各种注解来定制序列化和反序列化行为。将此配
+ * 置设为 false,表示不依赖这些注解来进行相关操作,而是更多地依据全局配置(如上述其他配置
+ * 项)来控制序列化和反序列化过程,适用于希望统一管理 JSON 处理规则,减少因注解使用不当或
+ * 过多导致的复杂性的场景
+ * 7. addModule(new JavaTimeModule())
+ * 这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
+ *
+ * 8. .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
+ * 所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
+ *
+ * 9. .addModule(new SimpleModule().addSerializer(LocalDateTime.class, new
+ * LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
+ * //序列时起作用
+ * .addDeserializer(LocalDateTime.class, new
+ * LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd
+ * HH:mm:ss"))) //反序列时起作用)
+ * 对于LocalDateTIme和LocalDate时间类型序列列化时转换为json字符串时可以按照指定格式转换,
+ * 反序列化时可以也可以将指定的时间字符串类型转换为LocalDateTIme和LocalDate。
+ */
+ static {
+ OBJECT_MAPPER = JsonMapper.builder().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
+ .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
+ // 不适用默认的dateTime进行序列化,使用JSR310的LocalDateTimeSerializer
+ .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
+ .configure(MapperFeature.USE_ANNOTATIONS, true)
+ // 重点,这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
+ .addModule(new JavaTimeModule())
+ .addModule(new SimpleModule()
+ .addSerializer(LocalDateTime.class,
+ new LocalDateTimeSerializer(
+ DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
+ .addDeserializer(LocalDateTime.class,
+ new LocalDateTimeDeserializer(
+ DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT))))
+ // 所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
+ .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
+ // 只针对非空的值进行序列化
+ .serializationInclusion(JsonInclude.Include.NON_NULL)
+ .build();
+ }
+
+ /**
+ * 禁用构造
+ */
+ private JsonUtil() {
+ }
+
+ /**
+ * 对象转Json格式字符串
+ *
+ * @param obj 对象
+ * @return Json格式字符串
+ * @param 对象类型
+ */
+ public static String obj2String(T obj) {
+ if (obj == null) {
+ return null;
+ }
+ try {
+ return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ log.warn("Parse Object to String error : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 对象转Json格式字符串(格式化的Json字符串)
+ *
+ * @param obj 对象
+ * @return 美化的Json格式字符串
+ * @param 对象类型
+ */
+ public static String obj2StringPretty(T obj) {
+ if (obj == null) {
+ return null;
+ }
+ try {
+ return obj instanceof String ? (String) obj
+ : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ log.warn("Parse Object to String error : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 字符串转换为自定义对象
+ *
+ * @param str 要转换的字符串
+ * @param clazz 自定义对象的class对象
+ * @return 自定义对象
+ * @param 对象类型
+ */
+ public static T string2Obj(String str, Class clazz) {
+ if (str == null || str.isEmpty() || clazz == null) {
+ return null;
+ }
+ try {
+ return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
+ } catch (Exception e) {
+ log.warn("Parse String to Object error : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 字符串转换为自定义对象,支持复杂的泛型嵌套
+ *
+ * @param str json字符串
+ * @param valueTypeRef 对象模板信息
+ * 使用如 new TypeReference>>() {}
+ * @return 对象类对应的对象
+ * @param 对象类
+ */
+ public static T string2Obj(String str, TypeReference valueTypeRef) {
+ if (StringUtils.isEmpty(str) || valueTypeRef == null) {
+ return null;
+ }
+ try {
+ return OBJECT_MAPPER.readValue(str, valueTypeRef);
+ } catch (Exception e) {
+ log.warn("Parse String to Object error : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 字符串转换为自定义字段转为list,支持List嵌套简单对象
+ *
+ * @param str json字符串
+ * @param clazz 对象类
+ * @return 对象列表
+ * @param 对象类型
+ */
+ public static List string2List(String str, Class clazz) {
+ if (str == null || str.isEmpty() || clazz == null) {
+ return null;
+ }
+ JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(List.class, clazz);
+ try {
+ return OBJECT_MAPPER.readValue(str, javaType);
+ } catch (IOException e) {
+ log.warn("Parse String to List error : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 字符串转换为自定义字段转为map,支持Map嵌套简单对象
+ *
+ * @param str str 字符串信息
+ * @param valueClass valueClass value的类别
+ * @return map对象
+ * @param value 的类型
+ */
+ public static Map string2Map(String str, Class valueClass) {
+ if (str == null || str.isEmpty() || valueClass == null) {
+ return null;
+ }
+ JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructMapType(LinkedHashMap.class,
+ String.class, valueClass);
+ try {
+ return OBJECT_MAPPER.readValue(str, javaType);
+ } catch (JsonProcessingException e) {
+ log.warn("Parse String to Map error : {}", e.getMessage());
+ return null;
+ }
+ }
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/ServletUtil.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/ServletUtil.java
new file mode 100644
index 0000000..6efd2ea
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/ServletUtil.java
@@ -0,0 +1,157 @@
+package yuxingshi.ssm.common.core.utils;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import reactor.core.publisher.Mono;
+import yuxingshi.ssm.common.core.constants.CommonConstants;
+import yuxingshi.ssm.common.core.domain.vo.R;
+
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+/**
+ * Servlet工具类
+ */
+public class ServletUtil {
+
+ /**
+ * 内容编码
+ *
+ * @param str 内容
+ * @return 编码后的内容
+ */
+ public static String urlEncode(String str) {
+ try {
+ return URLEncoder.encode(str, CommonConstants.UTF8);
+ } catch (UnsupportedEncodingException e) {
+ return StringUtils.EMPTY;
+ }
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return 无
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, Object value, int code) {
+ return webFluxResponseWriter(response, HttpStatus.OK, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return 无
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code) {
+ //修改了
+ return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param contentType content-type
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return 无
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code) {
+ response.setStatusCode(status);
+ response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
+ R> result = R.fail(code, value.toString());
+ DataBuffer dataBuffer = response.bufferFactory().wrap(JsonUtil.obj2String(result).getBytes());
+ return response.writeWith(Mono.just(dataBuffer));
+ }
+
+ /**
+ * 获取request
+ *
+ * @return request对象
+ */
+ public static HttpServletRequest getRequest() {
+ try {
+ return getRequestAttributes().getRequest();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * 获取request属性信息
+ *
+ * @return request属性
+ */
+ public static ServletRequestAttributes getRequestAttributes() {
+ try {
+ RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+ return (ServletRequestAttributes) attributes;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * 请求里面添加Header
+ * @param mutate 请求
+ * @param name 键
+ * @param value 值
+ */
+ public static void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) {
+ if(value == null) {
+ return;
+ }
+ String valueStr = value.toString();
+ String valueEncode = urlEncode(valueStr);
+ mutate.header(name,valueEncode);
+ }
+
+ /**
+ * 获取请求IP:
+ * 用户的真实IP不能使用request.getRemoteAddr()
+ * 这是因为可能会使用一些代理软件,这样ip获取就不准确了
+ * 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。
+ * @return
+ */
+ public static String getRequestIp() {
+ HttpServletRequest request = getRequest();
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ return ip;
+ }
+
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/StringUtil.java b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/StringUtil.java
new file mode 100644
index 0000000..9f98c60
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java/yuxingshi/ssm/common/core/utils/StringUtil.java
@@ -0,0 +1,56 @@
+package yuxingshi.ssm.common.core.utils;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.List;
+
+/**
+ * 字符串工具类
+ */
+public class StringUtil extends StringUtils{
+ /**
+ * 判断指定字符串是否与指定匹配规则链表中的任意一个匹配规则匹配
+ *
+ * @param str 指定字符串
+ * @param patternList 匹配规则链表
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, List patternList)
+ {
+ if (StringUtils.isEmpty(str) || CollectionUtils.isEmpty(patternList))
+ {
+ return false;
+ }
+ for (String pattern : patternList)
+ {
+ if (isMatch(pattern, str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * 判断url是否与规则匹配
+ *
+ * 匹配规则:
+ * 精确匹配
+ * 匹配规则中包含 ? 表示任意单个字符;
+ * 匹配规则中包含 * 表示一层路径内的任意字符串,不可跨层级;
+ * 匹配规则中包含 ** 表示任意层路径的任意字符,可跨层级
+ *
+ * @param pattern 匹配规则
+ * @param url 需要匹配的url
+ * @return 是否匹配
+ */
+ public static boolean isMatch(String pattern, String url)
+ {
+ if (StringUtils.isEmpty(url) || StringUtils.isEmpty(pattern)) {
+ return false;
+ }
+ AntPathMatcher matcher = new AntPathMatcher();
+ return matcher.match(pattern, url);
+ }
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/pom.xml b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/pom.xml
new file mode 100644
index 0000000..1b291c8
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm-common
+ 1.0-SNAPSHOT
+
+
+ yuxingshi.ssm.common.intercepter
+ yuxingshi-ssm-intercepter
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ yuxingshi.ssm.common.core
+ yuxingshi-ssm-core
+ 1.0-SNAPSHOT
+
+
+ yuxingshi.ssm.common.security
+ yuxingshi-ssm-security
+ 1.0-SNAPSHOT
+ compile
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/config/WebConfig.java b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/config/WebConfig.java
new file mode 100644
index 0000000..05e268d
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/config/WebConfig.java
@@ -0,0 +1,22 @@
+package yuxingshi.ssm.common.intercepter.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import yuxingshi.ssm.common.intercepter.filer.AuthInterceptor;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private AuthInterceptor authInterceptor;
+
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(authInterceptor)
+ .addPathPatterns("/**")
+ .excludePathPatterns("/**/login/**");
+ }
+}
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/filer/AuthInterceptor.java b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/filer/AuthInterceptor.java
new file mode 100644
index 0000000..a6f72b6
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java/yuxingshi/ssm/common/intercepter/filer/AuthInterceptor.java
@@ -0,0 +1,37 @@
+package yuxingshi.ssm.common.intercepter.filer;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import yuxingshi.ssm.common.security.service.TokenService;
+import yuxingshi.ssm.common.security.utils.SecurityUtil;
+
+/**
+ * 用户身份认证拦截器
+ */
+@Slf4j
+@Component
+public class AuthInterceptor implements HandlerInterceptor {
+
+
+ @Autowired
+ private TokenService tokenService;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request,
+ HttpServletResponse response,
+ Object handler) {
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request,
+ HttpServletResponse response,
+ Object handler,
+ Exception ex) {
+ }
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..c7918ad
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+yuxingshi.ssm.common.intercepter.config.WebConfig
+yuxingshi.ssm.common.intercepter.filer.AuthInterceptor
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/pom.xml b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/pom.xml
new file mode 100644
index 0000000..3400d52
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm-common
+ 1.0-SNAPSHOT
+
+
+ yuxingshi.ssm.common.mybatisplus
+ yuxingshi-ssm-mybatisplus
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+
+
+ yuxingshi.ssm.common.core
+ yuxingshi-ssm-core
+ 1.0-SNAPSHOT
+
+
+ com.a3test.component
+ idworker-snowflake
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/config/MyBatisPlusConfig.java b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/config/MyBatisPlusConfig.java
new file mode 100644
index 0000000..91fa9c0
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/config/MyBatisPlusConfig.java
@@ -0,0 +1,25 @@
+package yuxingshi.ssm.common.mybatisplus.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * MyBatisPlus配置类
+ */
+@Configuration
+public class MyBatisPlusConfig {
+
+ /**
+ * MyBatisPlus拦截器(用于分页)
+ */
+ @Bean
+ public MybatisPlusInterceptor paginationInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ //添加MySQL的分页拦截器
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+ }
+}
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/domain/BaseEntity.java b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/domain/BaseEntity.java
new file mode 100644
index 0000000..6096f49
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/domain/BaseEntity.java
@@ -0,0 +1,21 @@
+package yuxingshi.ssm.common.mybatisplus.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+public class BaseEntity {
+
+
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createdTime;
+
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updatedTime;
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/handler/MyMetaObjectHandler.java b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/handler/MyMetaObjectHandler.java
new file mode 100644
index 0000000..ac48278
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java/yuxingshi/ssm/common/mybatisplus/handler/MyMetaObjectHandler.java
@@ -0,0 +1,25 @@
+package yuxingshi.ssm.common.mybatisplus.handler;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+@Slf4j
+@Component
+public class MyMetaObjectHandler implements MetaObjectHandler { ;
+
+ @Override
+ public void insertFill(MetaObject metaObject) {
+ this.strictInsertFill(metaObject,"createdTime", LocalDateTime.class,LocalDateTime.now());
+ this.strictInsertFill(metaObject,"updatedTime", LocalDateTime.class,LocalDateTime.now());
+ }
+
+ @Override
+ public void updateFill(MetaObject metaObject) {
+ this.strictInsertFill(metaObject,"updatedTime", LocalDateTime.class,LocalDateTime.now());
+ }
+
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..8a70168
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+yuxingshi.ssm.common.mybatisplus.config.MyBatisPlusConfig
+yuxingshi.ssm.common.mybatisplus.handler.MyMetaObjectHandler
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-redis/pom.xml b/yuxingshi-ssm-common/yuxingshi-ssm-redis/pom.xml
new file mode 100644
index 0000000..a7fe225
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-redis/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+ yuxingshi
+ yuxingshi-ssm-common
+ 1.0-SNAPSHOT
+
+
+ yuxingshi.ssm.common.redis
+ yuxingshi-ssm-redis
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.springframework.boot
+ spring-boot-starter-json
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+
+
+ org.projectlombok
+ lombok
+
+
+ yuxingshi.ssm.common.core
+ yuxingshi-ssm-core
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/config/RedisConfig.java b/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/config/RedisConfig.java
new file mode 100644
index 0000000..ab5406a
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/config/RedisConfig.java
@@ -0,0 +1,118 @@
+package yuxingshi.ssm.common.redis.config;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import yuxingshi.ssm.common.core.constants.CommonConstants;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class RedisConfig {
+
+ private static final Logger log = LoggerFactory.getLogger(RedisConfig.class);
+
+ /**
+ * 配置RedisTemplate并定义序列化规则
+ *
+ * @param redisConnectionFactory redis连接工厂(由Spring Boot自动注入)
+ * @return 自定义序列化规则的Redis操作模板
+ *
+ * 关键配置说明:
+ * 1. setKeySerializer/setHashKeySerializer:
+ * - 使用StringRedisSerializer序列化String类型的键和Hash的字段名
+ * - 确保键可读且兼容所有Redis命令
+ * 2. setValueSerializer:
+ * - 值使用GenericJackson2JsonRedisSerializer进行JSON序列化
+ * - 支持复杂对象存储并保留类型信息
+ * 3. setHashValueSerializer:
+ * - Hash类型的值同样使用JSON序列化器
+ * 4. afterPropertiesSet():
+ * - 初始化模板确保配置生效
+ *
+ *
+ */
+ @Bean(name = "customRedisTemplate")
+ public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+ log.info("Configure Redis serialization");
+ RedisTemplate redisTemplate = new RedisTemplate<>();
+ redisTemplate.setConnectionFactory(redisConnectionFactory);
+ redisTemplate.setKeySerializer(new StringRedisSerializer());
+ redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+ GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer =
+ createJacksonSerializer();
+ redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+ redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
+ redisTemplate.afterPropertiesSet();
+ return redisTemplate;
+ }
+
+
+ /**
+ * 创建自定义Jackson序列化器
+ *
+ * @return 配置了安全策略的JSON序列化器
+ *
+ * ObjectMapper关键配置详解:
+ * 1. FAIL_ON_UNKNOWN_PROPERTIES(false):
+ * - 反序列化时忽略JSON中的未知字段,增强兼容性
+ * 2. WRITE_DATES_AS_TIMESTAMPS(false):
+ * - 禁用日期转时间戳,使用格式化字符串输出日期
+ * 3. FAIL_ON_EMPTY_BEANS(false):
+ * - 允许序列化空Bean对象而不抛异常
+ * 4. FAIL_ON_INVALID_SUBTYPE(false):
+ * - 忽略无效子类型错误,提高容错性
+ * 5. WRITE_DATE_KEYS_AS_TIMESTAMPS(false):
+ * - Map中的日期键也使用格式化字符串
+ * 6. defaultDateFormat():
+ * - 统一日期格式为"yyyy-MM-dd HH:mm:ss"标准格式
+ * 7. USE_ANNOTATIONS(false):
+ * - 禁用Jackson注解处理(根据需求可选)
+ * 8. JavaTimeModule():
+ * - 注册Java8时间模块(LocalDateTime等支持)
+ * 9. serializationInclusion(NON_NULL):
+ * - 序列化时自动忽略null值字段
+ */
+ public GenericJackson2JsonRedisSerializer createJacksonSerializer() {
+ // 创建自定义日期格式
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT);
+
+ // 创建并配置 JavaTimeModule
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
+ javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
+
+ ObjectMapper objectMapper =
+ JsonMapper.builder()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
+ .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
+ .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
+ .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
+ .configure(MapperFeature.USE_ANNOTATIONS, false)
+ // 注册自定义时间模块
+ .addModule(javaTimeModule)
+ .serializationInclusion(JsonInclude.Include.NON_NULL)
+ .build();
+
+ return new GenericJackson2JsonRedisSerializer(objectMapper);
+ }
+}
diff --git a/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/server/RedisService.java b/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/server/RedisService.java
new file mode 100644
index 0000000..2cfe67e
--- /dev/null
+++ b/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java/yuxingshi/ssm/common/redis/server/RedisService.java
@@ -0,0 +1,1002 @@
+package yuxingshi.ssm.common.redis.server;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.DataAccessException;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import yuxingshi.ssm.common.core.utils.JsonUtil;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Service
+public class RedisService {
+
+ @Qualifier("customRedisTemplate")
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ // ******************基本操作******************
+
+ /**
+ * 设置有效时间 (时间单位默认秒)
+ *
+ * @param key Redis键
+ * @param timeout 超时时间
+ * @return true=设置成功;false=设置失败
+ */
+ public boolean expire(final String key, final long timeout) {
+ return expire(key, timeout, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 设置有效时间 (可指定时间单位)
+ *
+ * @param key Redis键
+ * @param timeout 超时时间
+ * @param unit 时间单位
+ * @return true=设置成功;false=设置失败
+ */
+ public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+ return redisTemplate.expire(key, timeout, unit);
+ }
+
+ /**
+ * 获取有效时间
+ *
+ * @param key Redis键
+ * @return 有效时间
+ */
+ public long getExpire(final String key) {
+ return redisTemplate.getExpire(key);
+ }
+
+ /**
+ * 判断 key是否存在
+ *
+ * @param key 键
+ * @return true=存在;false=不存在
+ */
+ public Boolean hasKey(String key) {
+ return redisTemplate.hasKey(key);
+ }
+
+ /**
+ * 删除单个数据
+ *
+ * @param key 缓存的键值
+ * @return 是否成功 true=删除成功;false=删除失败
+ */
+
+ /**
+ * 根据提供的键模式查找 Redis 中匹配的键
+ *
+ * @param pattern 要查找的键的模式
+ * @return 键列表
+ */
+ public Collection keys(final String pattern) {
+ return redisTemplate.keys(pattern);
+ }
+
+ /**
+ * 重命名key
+ *
+ * @param oldKey 原来key
+ * @param newKey 新key
+ */
+ public void renameKey(String oldKey, String newKey) {
+ redisTemplate.rename(oldKey, newKey);
+ }
+
+ /**
+ * 删除单个数据
+ *
+ * @param key 缓存的键值
+ * @return 是否成功 true=删除成功;false=删除失败
+ */
+ public boolean deleteObject(final String key) {
+ return redisTemplate.delete(key);
+ }
+
+ /**
+ * 删除多个数据
+ *
+ * @param collection 多个数据对应的缓存的键值
+ * @return 是否删除了对象 true=删除成功;false=删除失败
+ */
+ public boolean deleteObject(final Collection collection) {
+ return redisTemplate.delete(collection) > 0;
+ }
+
+ /**
+ * 删除多个数据(重载方法)
+ *
+ * @param keys 多个数据对应的缓存的键值列表
+ * @return 删除的数量
+ */
+ public long deleteObjects(final List keys) {
+ if (keys == null || keys.isEmpty()) {
+ return 0;
+ }
+ return redisTemplate.delete(keys);
+ }
+
+ // ******************操作String******************
+
+ /**
+ * 缓存存储数据,值存储JSON数据
+ *
+ * @param key 键
+ * @param value 值
+ */
+ public void setCacheObject(final String key, final T value) {
+ redisTemplate.opsForValue().set(key, value);
+ }
+
+ /**
+ * 批量缓存存储数据,值存储JSON数据
+ *
+ * @param keyValueMap 键值对映射
+ */
+ public void setCacheObjectBatch(final Map keyValueMap, long timeout, TimeUnit unit) {
+ if (keyValueMap == null || keyValueMap.isEmpty()) {
+ return; // 空映射直接返回,避免无效操作
+ }
+
+ // 使用Pipeline批量操作提升性能
+ redisTemplate.executePipelined(new SessionCallback