From e2de84d5a91fa7bd09eb59c5c5acc11e857da9c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:30:32 +0800
Subject: [PATCH 1/7] =?UTF-8?q?refactor(project):=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E9=A1=B9=E7=9B=AE=E9=85=8D=E7=BD=AE=E5=92=8C=E5=BC=82=E5=B8=B8?=
=?UTF-8?q?=E5=A4=84=E7=90=86=E6=9C=BA=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 更新 Docker Compose 配置从版本 1 到 3.8,并修改服务构建方式
- 将异常处理中的 ResponseCode 替换为 SystemStatus 枚举
- 统一全局异常处理器返回类型为 RetObj,替换原有的 GenericResponse
- 修复 JWT 工具类中的空指针判断逻辑错误
- 优化 RSA 加密工具类,使用 Java 自带 Base64 实现替代 Apache 工具类
- 添加 Spring Security 密码编码器支持,增强用户密码安全性
- 完善日志配置文件,增加多种环境的日志输出策略
- 优化 Dockerfile 使用 JDK 17 环境并改进构建参数配置
---
Dockerfile | 29 +++----
pom.xml | 4 +
.../basedemo/common/enums/SystemStatus.java | 7 +-
.../common/exception/BusinessException.java | 21 ++---
.../exception/GlobalExceptionHandler.java | 22 ++---
.../common/exception/LoginException.java | 21 ++---
.../cn/xf/basedemo/common/model/RetObj.java | 8 +-
.../basedemo/common/utils/JwtTokenUtils.java | 2 +-
.../cn/xf/basedemo/common/utils/RSAUtils.java | 30 +++----
.../common/utils/RequestHeaderUtil.java | 4 +-
.../interceptor/TokenInterceptor.java | 15 ++--
.../service/impl/UserServiceImpl.java | 12 +--
.../resources/docker/boot-docker-compose.yml | 12 +--
src/main/resources/logback-spring.xml | 85 +++++++++++++++++++
14 files changed, 180 insertions(+), 92 deletions(-)
create mode 100644 src/main/resources/logback-spring.xml
diff --git a/Dockerfile b/Dockerfile
index 5f05bca..d5640e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,22 +1,17 @@
-# java8运行环境
-FROM openjdk:8-jdk-alpine
-# 作者名称
-MAINTAINER xiongfeng
+# 使用 JDK 17 轻量级运行环境
+FROM eclipse-temurin:17-jre-alpine
+
+# 作者信息
+LABEL maintainer="xiongfeng"
# 切换工作目录
WORKDIR /root/java
-#1. coding自动化部署
-#COPY target/*.jar app.jar
-## 暴露端口8080
-##EXPOSE 8080
-## 运行命令
-#ENTRYPOINT ["java","-Djava.security.egd=file:/dev/urandom","-Dfile.encoding=UTF-8","-Duser.timezone=Asia/Shanghai","-XX:MaxDirectMemorySize=1024m","-XX:MetaspaceSize=256m","-XX:MaxMetaspaceSize=512m","-XX:MaxRAMPercentage=80.0","-jar","app.jar"]
+# 将编译好的 jar 包复制到容器中,避免硬编码包名版本号
+COPY target/*.jar app.jar
-#2. 手动部署项目到docker环境中
-# 添加demo-start-1.0.0.jar文件到docker环境内
-ADD xf-boot-base-1.0.1.jar /root/java/xf-boot-base-1.0.1.jar
-## 暴露端口8080
-#EXPOSE 8080
-## 运行命令
-ENTRYPOINT ["java", "-server", "-Xms512m", "-Xmx512m", "-jar", "/root/java/xf-boot-base-1.0.1.jar"]
+# 暴露端口 8089 (对齐 application.yml)
+EXPOSE 8089
+
+# 运行命令,加入垃圾回收和内存优化参数,以及时区与字符编码设置
+ENTRYPOINT ["java", "-server", "-Xms512m", "-Xmx512m", "-Dfile.encoding=UTF-8", "-Duser.timezone=Asia/Shanghai", "-jar", "app.jar"]
diff --git a/pom.xml b/pom.xml
index d2a9b18..d356dbc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,10 @@
java-jwt
${jwt.version}
+
+ org.springframework.security
+ spring-security-crypto
+
org.apache.commons
diff --git a/src/main/java/cn/xf/basedemo/common/enums/SystemStatus.java b/src/main/java/cn/xf/basedemo/common/enums/SystemStatus.java
index 764de77..15c5d61 100644
--- a/src/main/java/cn/xf/basedemo/common/enums/SystemStatus.java
+++ b/src/main/java/cn/xf/basedemo/common/enums/SystemStatus.java
@@ -5,8 +5,11 @@ import lombok.Getter;
@Getter
public enum SystemStatus {
- SUSSES(200, "请求成功"),
- UNAVAILABILITY(401, "token无效"),
+ SUCCESS(200, "请求成功"),
+ USER_INPUT_ERROR(400, "参数或用户输入错误"),
+ UNAUTHORIZED(401, "token无效"),
+ FORBIDDEN(403, "禁止访问"),
+ TOO_FREQUENT_VISIT(429, "访问太频繁,请休息一会儿"),
ERROR(500, "系统异常")
;
diff --git a/src/main/java/cn/xf/basedemo/common/exception/BusinessException.java b/src/main/java/cn/xf/basedemo/common/exception/BusinessException.java
index 23be9d2..65d8c56 100644
--- a/src/main/java/cn/xf/basedemo/common/exception/BusinessException.java
+++ b/src/main/java/cn/xf/basedemo/common/exception/BusinessException.java
@@ -1,5 +1,6 @@
package cn.xf.basedemo.common.exception;
+import cn.xf.basedemo.common.enums.SystemStatus;
import lombok.Getter;
/**
@@ -10,29 +11,29 @@ import lombok.Getter;
*/
@Getter
public class BusinessException extends RuntimeException{
- private final ResponseCode code;
+ private final SystemStatus status;
public BusinessException() {
- super(String.format("%s", ResponseCode.INTERNAL_ERROR.getMessage()));
- this.code = ResponseCode.INTERNAL_ERROR;
+ super(String.format("%s", SystemStatus.ERROR.getErrorMessage()));
+ this.status = SystemStatus.ERROR;
}
public BusinessException(Throwable e) {
super(e);
- this.code = ResponseCode.INTERNAL_ERROR;
+ this.status = SystemStatus.ERROR;
}
public BusinessException(String msg) {
- this(ResponseCode.INTERNAL_ERROR, msg);
+ this(SystemStatus.ERROR, msg);
}
- public BusinessException(ResponseCode code) {
- super(String.format("%s", code.getMessage()));
- this.code = code;
+ public BusinessException(SystemStatus status) {
+ super(String.format("%s", status.getErrorMessage()));
+ this.status = status;
}
- public BusinessException(ResponseCode code, String msg) {
+ public BusinessException(SystemStatus status, String msg) {
super(msg);
- this.code = code;
+ this.status = status;
}
}
diff --git a/src/main/java/cn/xf/basedemo/common/exception/GlobalExceptionHandler.java b/src/main/java/cn/xf/basedemo/common/exception/GlobalExceptionHandler.java
index 0bcc700..42bbd7a 100644
--- a/src/main/java/cn/xf/basedemo/common/exception/GlobalExceptionHandler.java
+++ b/src/main/java/cn/xf/basedemo/common/exception/GlobalExceptionHandler.java
@@ -1,5 +1,7 @@
package cn.xf.basedemo.common.exception;
+import cn.xf.basedemo.common.enums.SystemStatus;
+import cn.xf.basedemo.common.model.RetObj;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
@@ -28,9 +30,9 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(LoginException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
- public GenericResponse handleLoginException(LoginException e, HttpServletRequest request) {
- log.warn("认证失败 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getCode(), e.getMessage());
- return new GenericResponse<>(e.getCode(), null, e.getMessage());
+ public RetObj handleLoginException(LoginException e, HttpServletRequest request) {
+ log.warn("认证失败 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getStatus().getCode(), e.getMessage());
+ return new RetObj<>(e.getStatus().getCode(), e.getMessage());
}
/**
@@ -38,9 +40,9 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST) // 或者使用 HttpStatus.OK,根据前端约定
- public GenericResponse handleBusinessException(BusinessException e, HttpServletRequest request) {
- log.warn("业务异常 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getCode(), e.getMessage());
- return new GenericResponse<>(e.getCode(), null, e.getMessage());
+ public RetObj handleBusinessException(BusinessException e, HttpServletRequest request) {
+ log.warn("业务异常 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getStatus().getCode(), e.getMessage());
+ return new RetObj<>(e.getStatus().getCode(), e.getMessage());
}
/**
@@ -48,7 +50,7 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
- public GenericResponse handleValidationException(Exception e, HttpServletRequest request) {
+ public RetObj handleValidationException(Exception e, HttpServletRequest request) {
BindingResult bindingResult = null;
if (e instanceof MethodArgumentNotValidException) {
bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
@@ -64,7 +66,7 @@ public class GlobalExceptionHandler {
}
}
log.warn("参数校验失败 [URL:{}]: {}", request.getRequestURI(), errorMsg);
- return new GenericResponse<>(ResponseCode.USER_INPUT_ERROR.getCode(), null, errorMsg);
+ return new RetObj<>(SystemStatus.USER_INPUT_ERROR.getCode(), errorMsg);
}
/**
@@ -72,9 +74,9 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
- public GenericResponse handleSystemException(Exception e, HttpServletRequest request) {
+ public RetObj handleSystemException(Exception e, HttpServletRequest request) {
// 生产级关键点:必须记录异常堆栈,否则无法排查 BUG
log.error("系统发生未知异常 [URL:{}]", request.getRequestURI(), e);
- return new GenericResponse<>(500, null, "系统内部繁忙,请稍后再试");
+ return new RetObj<>(SystemStatus.ERROR.getCode(), "系统内部繁忙,请稍后再试");
}
}
diff --git a/src/main/java/cn/xf/basedemo/common/exception/LoginException.java b/src/main/java/cn/xf/basedemo/common/exception/LoginException.java
index 2cdeeec..f415378 100644
--- a/src/main/java/cn/xf/basedemo/common/exception/LoginException.java
+++ b/src/main/java/cn/xf/basedemo/common/exception/LoginException.java
@@ -1,5 +1,6 @@
package cn.xf.basedemo.common.exception;
+import cn.xf.basedemo.common.enums.SystemStatus;
import lombok.Getter;
/**
@@ -11,30 +12,30 @@ import lombok.Getter;
@Getter
public class LoginException extends RuntimeException{
- private final ResponseCode code;
+ private final SystemStatus status;
public LoginException() {
- super(String.format("%s", ResponseCode.AUTHENTICATION_NEEDED.getMessage()));
- this.code = ResponseCode.AUTHENTICATION_NEEDED;
+ super(String.format("%s", SystemStatus.UNAUTHORIZED.getErrorMessage()));
+ this.status = SystemStatus.UNAUTHORIZED;
}
public LoginException(Throwable e) {
super(e);
- this.code = ResponseCode.AUTHENTICATION_NEEDED;
+ this.status = SystemStatus.UNAUTHORIZED;
}
public LoginException(String msg) {
- this(ResponseCode.AUTHENTICATION_NEEDED, msg);
+ this(SystemStatus.UNAUTHORIZED, msg);
}
- public LoginException(ResponseCode code) {
- super(String.format("%s", code.getMessage()));
- this.code = code;
+ public LoginException(SystemStatus status) {
+ super(String.format("%s", status.getErrorMessage()));
+ this.status = status;
}
- public LoginException(ResponseCode code, String msg) {
+ public LoginException(SystemStatus status, String msg) {
super(msg);
- this.code = code;
+ this.status = status;
}
}
diff --git a/src/main/java/cn/xf/basedemo/common/model/RetObj.java b/src/main/java/cn/xf/basedemo/common/model/RetObj.java
index 282a3c2..85a4468 100644
--- a/src/main/java/cn/xf/basedemo/common/model/RetObj.java
+++ b/src/main/java/cn/xf/basedemo/common/model/RetObj.java
@@ -46,20 +46,20 @@ public class RetObj {
}
public static RetObj success() {
- return new RetObj(SystemStatus.SUSSES);
+ return new RetObj<>(SystemStatus.SUCCESS);
}
public static RetObj success(T data) {
- return new RetObj(SystemStatus.SUSSES, data);
+ return new RetObj<>(SystemStatus.SUCCESS, data);
}
public static RetObj error(SystemStatus status) {
- return new RetObj(status);
+ return new RetObj<>(status);
}
public static RetObj error(String errorMsg) {
- return new RetObj(SystemStatus.ERROR.getCode(), errorMsg);
+ return new RetObj<>(SystemStatus.ERROR.getCode(), errorMsg);
}
}
diff --git a/src/main/java/cn/xf/basedemo/common/utils/JwtTokenUtils.java b/src/main/java/cn/xf/basedemo/common/utils/JwtTokenUtils.java
index ce73bc5..d70958f 100644
--- a/src/main/java/cn/xf/basedemo/common/utils/JwtTokenUtils.java
+++ b/src/main/java/cn/xf/basedemo/common/utils/JwtTokenUtils.java
@@ -106,7 +106,7 @@ public class JwtTokenUtils {
*/
public static Integer getUserId(String token) {
Map claims = verifyToken(token);
- if (claims != null) {
+ if (claims == null) {
return null;
}
diff --git a/src/main/java/cn/xf/basedemo/common/utils/RSAUtils.java b/src/main/java/cn/xf/basedemo/common/utils/RSAUtils.java
index ab2fc3d..667d729 100644
--- a/src/main/java/cn/xf/basedemo/common/utils/RSAUtils.java
+++ b/src/main/java/cn/xf/basedemo/common/utils/RSAUtils.java
@@ -1,8 +1,5 @@
package cn.xf.basedemo.common.utils;
-import org.apache.tomcat.util.codec.binary.Base64;
-import org.apache.tomcat.util.http.fileupload.IOUtils;
-
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
@@ -11,6 +8,7 @@ import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@@ -20,7 +18,7 @@ import java.util.Map;
* @description: 加密工具类
* @author: xiongfeng
* @create: 2022-06-20 10:37
- **/
+ * **/
public class RSAUtils {
//算法类型
@@ -49,10 +47,10 @@ public class RSAUtils {
kpg.initialize(ENCRYPT_SIZE);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey aPublic = keyPair.getPublic();
- String publicKey = Base64.encodeBase64URLSafeString(aPublic.getEncoded());
+ String publicKey = Base64.getUrlEncoder().withoutPadding().encodeToString(aPublic.getEncoded());
PrivateKey aPrivate = keyPair.getPrivate();
- String privateKey = Base64.encodeBase64URLSafeString(aPrivate.getEncoded());
+ String privateKey = Base64.getUrlEncoder().withoutPadding().encodeToString(aPrivate.getEncoded());
Map map = new HashMap<>();
@@ -73,7 +71,7 @@ public class RSAUtils {
public static RSAPublicKey getPublicKey(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
// 通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64URLSafe(publicKeyStr));
+ X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getUrlDecoder().decode(publicKeyStr));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
@@ -89,7 +87,7 @@ public class RSAUtils {
public static RSAPrivateKey getPrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64URLSafe(privateKeyStr));
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(privateKeyStr));
RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
return privateKey;
}
@@ -109,8 +107,7 @@ public class RSAUtils {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(data.getBytes());
- return Base64.encodeBase64URLSafeString(bytes);
-// return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
} catch (Exception e) {
throw new RuntimeException();
}
@@ -121,9 +118,7 @@ public class RSAUtils {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
-// byte[] bytes = cipher.doFinal(Base64.decodeBase64(data.getBytes(CHARSET)));
-// return new String(bytes);
- return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data.getBytes(CHARSET), 0, data.getBytes(CHARSET).length), privateKey.getModulus().bitLength()), CHARSET);
+ return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getUrlDecoder().decode(data.getBytes(CHARSET)), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
@@ -137,11 +132,10 @@ public class RSAUtils {
} else {
maxBlock = keySize / 8 - 11;
}
- ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
- byte[] buff;
int i = 0;
- try {
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ byte[] buff;
while (datas.length > offSet) {
if (datas.length - offSet > maxBlock) {
//可以调用以下的doFinal()方法完成加密或解密数据:
@@ -153,12 +147,10 @@ public class RSAUtils {
i++;
offSet = i * maxBlock;
}
+ return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
}
- byte[] resultDatas = out.toByteArray();
- IOUtils.closeQuietly(out);
- return resultDatas;
}
public static void main(String[] args) {
diff --git a/src/main/java/cn/xf/basedemo/common/utils/RequestHeaderUtil.java b/src/main/java/cn/xf/basedemo/common/utils/RequestHeaderUtil.java
index 2846697..63a9d68 100644
--- a/src/main/java/cn/xf/basedemo/common/utils/RequestHeaderUtil.java
+++ b/src/main/java/cn/xf/basedemo/common/utils/RequestHeaderUtil.java
@@ -52,9 +52,9 @@ public class RequestHeaderUtil {
public static String getToken(HttpServletRequest request) {
//登录处理
String token = request.getHeader("Authorization");
- if (StringUtils.isEmpty(token))
+ if (!StringUtils.hasText(token))
token = request.getParameter("token");
- if (StringUtils.isEmpty(token)) {
+ if (!StringUtils.hasText(token)) {
throw new LoginException("请先登录");
}
diff --git a/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java b/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java
index 98daf8b..0cdbff2 100644
--- a/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java
+++ b/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java
@@ -1,7 +1,7 @@
package cn.xf.basedemo.interceptor;
import cn.xf.basedemo.common.exception.LoginException;
-import cn.xf.basedemo.common.exception.ResponseCode;
+import cn.xf.basedemo.common.enums.SystemStatus;
import cn.xf.basedemo.common.model.LoginUser;
import cn.xf.basedemo.common.utils.ApplicationContextUtils;
import com.alibaba.fastjson.JSONObject;
@@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit;
* @description:
* @author: xiongfeng
* @create: 2022-06-16 14:17
+ * @component
**/
@Component
public class TokenInterceptor implements HandlerInterceptor {
@@ -45,28 +46,28 @@ public class TokenInterceptor implements HandlerInterceptor {
}
//登录处理
String token = request.getHeader("Authorization");
- if (StringUtils.isEmpty(token))
+ if (!StringUtils.hasText(token))
token = request.getParameter("token");
- if (StringUtils.isEmpty(token)) {
+ if (!StringUtils.hasText(token)) {
throw new LoginException("请先登录");
}else {
//验证token
if (!token.startsWith("Bearer ")) {
- throw new LoginException(ResponseCode.USER_INPUT_ERROR);
+ throw new LoginException(SystemStatus.USER_INPUT_ERROR);
}
token = token.substring(7);
}
String value = (String) redisTemplate.opsForValue().get("token:" + token);
- if (StringUtils.isEmpty(value)) {
+ if (!StringUtils.hasText(value)) {
throw new LoginException();
}
JSONObject jsonObject = JSONObject.parseObject(value);
//JSON对象转换成Java对象
LoginUser loginUserInfo = JSONObject.toJavaObject(jsonObject, LoginUser.class);
if (loginUserInfo == null || loginUserInfo.getId() <= 0) {
- throw new LoginException(ResponseCode.USER_INPUT_ERROR);
+ throw new LoginException(SystemStatus.USER_INPUT_ERROR);
}
- redisTemplate.expire(token, 86700, TimeUnit.SECONDS);
+ redisTemplate.expire("token:" + token, 86700, TimeUnit.SECONDS);
//用户信息设置到上下文
SessionContext.getInstance().set(loginUserInfo);
diff --git a/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java
index 8d76202..a736644 100644
--- a/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java
+++ b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java
@@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@@ -46,10 +47,12 @@ public class UserServiceImpl implements UserService {
@Autowired
private RedisTemplate redisTemplate;
+ private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+
@Override
public RetObj login(LoginInfoRes res) {
- if (Objects.isNull(res) || StringUtils.isEmpty(res.getEncryptedData())) {
+ if (Objects.isNull(res) || !StringUtils.hasText(res.getEncryptedData())) {
return null;
}
String loginJson = "";
@@ -65,15 +68,14 @@ public class UserServiceImpl implements UserService {
e.printStackTrace();
return RetObj.error("账号或密码错误");
}
- if (!StringUtils.isEmpty(loginInfo.check())) {
+ if (StringUtils.hasText(loginInfo.check())) {
return RetObj.error(loginInfo.check());
}
//校验登录账号密码
- QueryWrapper queryWrapper = new QueryWrapper();
+ QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("account", loginInfo.getAccount());
- queryWrapper.eq("password", loginInfo.getPwd());
User user = userMapper.selectOne(queryWrapper);
- if (Objects.isNull(user)) {
+ if (Objects.isNull(user) || !passwordEncoder.matches(loginInfo.getPwd(), user.getPassword())) {
return RetObj.error("账号或密码错误");
}
LoginUser loginUser = new LoginUser();
diff --git a/src/main/resources/docker/boot-docker-compose.yml b/src/main/resources/docker/boot-docker-compose.yml
index 2658886..07f3e58 100644
--- a/src/main/resources/docker/boot-docker-compose.yml
+++ b/src/main/resources/docker/boot-docker-compose.yml
@@ -1,12 +1,14 @@
-version: '1'
+version: '3.8'
services:
- boot_docker_compose:
- image: remaindertime/boot_docker_compose:v1.0.0
- container_name: boot_docker_compose
+ xf-boot-base:
+ build:
+ context: ../../../
+ dockerfile: Dockerfile
+ container_name: xf-boot-base
environment:
- SERVER_ADDRESS=120.48.109.209
- MYSQL_NAME=root
- MYSQL_PWD=123456
- REDIS_PWD=123456
ports:
- - 8090:8088
\ No newline at end of file
+ - 8089:8089
\ No newline at end of file
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..77c427e
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,85 @@
+
+
+ xf-boot-base
+
+
+
+
+
+
+
+ ${log_pattern}
+ UTF-8
+
+
+
+
+
+ ${log_home}/base-info.log
+
+ ${log_home}/base-%d{yyyy-MM-dd}-info.%i.log
+ 200MB
+ 30
+ 10GB
+
+
+ ${log_pattern}
+ UTF-8
+
+
+ INFO
+
+
+
+
+
+ ${log_home}/base-error.log
+
+ ${log_home}/base-%d{yyyy-MM-dd}-error.%i.log
+ 200MB
+ 30
+ 5GB
+
+
+ ${log_pattern}
+ UTF-8
+
+
+ ERROR
+
+
+
+
+
+
+
+
+ ${logIps}
+ 5 minutes
+ 5 seconds
+ 30 seconds
+ sleeping
+
+ {"host":"${HOSTNAME}", "app_name":"${appName}"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 548525acdd32b3df00fbc8227e3c45f2a7856295 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:31:38 +0800
Subject: [PATCH 2/7] =?UTF-8?q?remove(logback):=20=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E6=9C=AC=E5=9C=B0=E5=92=8C=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83?=
=?UTF-8?q?=E7=9A=84=E6=97=A5=E5=BF=97=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除 src/main/resources/logback-spring-local.xml 配置文件
- 移除 src/main/resources/logback-spring-s.xml 配置文件
- 清理相关日志配置依赖项和属性设置
---
src/main/resources/logback-spring-local.xml | 88 ---------------------
src/main/resources/logback-spring-s.xml | 32 --------
2 files changed, 120 deletions(-)
delete mode 100644 src/main/resources/logback-spring-local.xml
delete mode 100644 src/main/resources/logback-spring-s.xml
diff --git a/src/main/resources/logback-spring-local.xml b/src/main/resources/logback-spring-local.xml
deleted file mode 100644
index 6a5ea82..0000000
--- a/src/main/resources/logback-spring-local.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
- logback
-
-
-
-
-
-
-
- info
-
-
- ${log_pattern}
- UTF-8
-
-
-
-
-
- ./${log_home}/base-%d{yyyy-MM-dd}-info.%i.log
-
- 200MB
-
- 3
-
-
-
- %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
- UTF-8
-
-
- info
-
-
-
-
-
- ./${log_home}/base-%d{yyyy-MM-dd}-error.%i.log
-
- 200MB
-
- 3
-
-
-
- %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
- UTF-8
-
-
- error
-
-
-
-
-
-
- ${logIps}
-
- 5 minutes
-
- 5 seconds
-
- 30 second
-
-
- sleeping
-
- {"host":"${HOSTNAME}", "app_name":"${appName}","plantVersion":"1"}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/logback-spring-s.xml b/src/main/resources/logback-spring-s.xml
deleted file mode 100644
index d13263e..0000000
--- a/src/main/resources/logback-spring-s.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
- ${APP_NAME}
-
-
-
- ${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log
- 30
-
-
- ${FILE_LOG_PATTERN}
-
-
-
-
-
- 120.48.109.209:4560
-
-
-
-
-
-
-
-
\ No newline at end of file
From 6e5a3a3142766e383eec887a8856c6a5660ca9d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:33:55 +0800
Subject: [PATCH 3/7] =?UTF-8?q?refactor(common):=20=E7=A7=BB=E9=99=A4?=
=?UTF-8?q?=E9=80=9A=E7=94=A8=E5=93=8D=E5=BA=94=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 删除了 GenericResponse 类及其所有构造方法
- 移除了与 ResponseCode 枚举的关联逻辑
- 清理了相关的泛型数据封装结构
---
.../common/exception/GenericResponse.java | 47 -------------------
1 file changed, 47 deletions(-)
delete mode 100644 src/main/java/cn/xf/basedemo/common/exception/GenericResponse.java
diff --git a/src/main/java/cn/xf/basedemo/common/exception/GenericResponse.java b/src/main/java/cn/xf/basedemo/common/exception/GenericResponse.java
deleted file mode 100644
index 227a2c1..0000000
--- a/src/main/java/cn/xf/basedemo/common/exception/GenericResponse.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package cn.xf.basedemo.common.exception;
-
-import lombok.Data;
-
-/**
- * @Author: xiongfeng
- * @CreateTime: 2023-11-08 13:47
- * @Description: TODO
- * @Version: 1.0
- */
-@Data
-public class GenericResponse {
- private int code;
-
- private T data;
-
- private String message;
-
- public GenericResponse() {};
-
- public GenericResponse(int code, T data) {
- this.code = code;
- this.data = data;
- }
-
- public GenericResponse(int code, T data, String message) {
- this(code, data);
- this.message = message;
- }
-
- public GenericResponse(ResponseCode responseCode) {
- this.code = responseCode.getCode();
- this.data = null;
- this.message = responseCode.getMessage();
- }
-
- public GenericResponse(ResponseCode responseCode, T data) {
- this(responseCode);
- this.data = data;
- }
-
- public GenericResponse(ResponseCode responseCode, T data, String message) {
- this(responseCode, data);
- this.message = message;
- }
-
-}
From 9554192e8575e4d1e5bc9ed3e6cc5c4ca2ca9df4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:41:24 +0800
Subject: [PATCH 4/7] =?UTF-8?q?feat(config):=20=E5=90=AF=E7=94=A8=E9=A9=BC?=
=?UTF-8?q?=E5=B3=B0=E5=91=BD=E5=90=8D=E5=88=B0=E4=B8=8B=E5=88=92=E7=BA=BF?=
=?UTF-8?q?=E6=98=A0=E5=B0=84=E5=B9=B6=E5=AE=8C=E5=96=84=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E5=AE=9E=E4=BD=93=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将 application-local.yml 和 application-pre.yml 中 mybatis-plus 的 map-underscore-to-camel-case 设置为 true
- 在 StringUtil 类中新增 camelToSnakeCase 方法用于驼峰转下划线命名
- 更新 camelToKebabCase 方法注释并修正转换逻辑
- 为 User 实体类添加 @TableId 注解配置自增主键
---
.../xf/basedemo/common/utils/StringUtil.java | 22 +++++++++++++++++--
.../cn/xf/basedemo/model/domain/User.java | 3 +++
src/main/resources/application-local.yml | 2 +-
src/main/resources/application-pre.yml | 2 +-
4 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/main/java/cn/xf/basedemo/common/utils/StringUtil.java b/src/main/java/cn/xf/basedemo/common/utils/StringUtil.java
index 844163a..69359f1 100644
--- a/src/main/java/cn/xf/basedemo/common/utils/StringUtil.java
+++ b/src/main/java/cn/xf/basedemo/common/utils/StringUtil.java
@@ -10,10 +10,10 @@ package cn.xf.basedemo.common.utils;
public class StringUtil {
/**
- * 驼峰命名法转下划线命名法
+ * 驼峰命名法转短横线命名法(kebab-case)
*
* @param camelCase 驼峰命名法字符串
- * @return 下划线命名法字符串
+ * @return 短横线命名法字符串
*/
public static String camelToKebabCase(String camelCase) {
if (camelCase == null || camelCase.isEmpty()) {
@@ -26,4 +26,22 @@ public class StringUtil {
// 转换为小写
return result.toLowerCase();
}
+
+ /**
+ * 驼峰命名法转下划线命名法(snake_case)
+ *
+ * @param camelCase 驼峰命名法字符串
+ * @return 下划线命名法字符串
+ */
+ public static String camelToSnakeCase(String camelCase) {
+ if (camelCase == null || camelCase.isEmpty()) {
+ return camelCase;
+ }
+
+ // 使用正则表达式将大写字母前插入一个"_"
+ String result = camelCase.replaceAll("([a-z])([A-Z])", "$1_$2");
+
+ // 转换为小写
+ return result.toLowerCase();
+ }
}
diff --git a/src/main/java/cn/xf/basedemo/model/domain/User.java b/src/main/java/cn/xf/basedemo/model/domain/User.java
index c506b2f..978afe5 100644
--- a/src/main/java/cn/xf/basedemo/model/domain/User.java
+++ b/src/main/java/cn/xf/basedemo/model/domain/User.java
@@ -1,5 +1,7 @@
package cn.xf.basedemo.model.domain;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -17,6 +19,7 @@ import java.util.Date;
@TableName(value = "xf_user")
public class User {
+ @TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String name;
diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml
index 1964d39..64c3783 100644
--- a/src/main/resources/application-local.yml
+++ b/src/main/resources/application-local.yml
@@ -66,7 +66,7 @@ springdoc:
mybatis-plus:
configuration:
- map-underscore-to-camel-case: false
+ map-underscore-to-camel-case: true
auto-mapping-behavior: full
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
mapper-locations: classpath*:mapper/**/*Mapper.xml
diff --git a/src/main/resources/application-pre.yml b/src/main/resources/application-pre.yml
index a172ef3..a911aa2 100644
--- a/src/main/resources/application-pre.yml
+++ b/src/main/resources/application-pre.yml
@@ -68,7 +68,7 @@ springdoc:
mybatis-plus:
configuration:
- map-underscore-to-camel-case: false
+ map-underscore-to-camel-case: true
auto-mapping-behavior: full
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
mapper-locations: classpath*:mapper/**/*Mapper.xml
From 270ac35e37bdf0242a4df28d541cbf1e0f800128 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:42:53 +0800
Subject: [PATCH 5/7] =?UTF-8?q?feat(config):=20=E5=90=AF=E7=94=A8=E9=A9=BC?=
=?UTF-8?q?=E5=B3=B0=E5=91=BD=E5=90=8D=E5=88=B0=E4=B8=8B=E5=88=92=E7=BA=BF?=
=?UTF-8?q?=E6=98=A0=E5=B0=84=E5=B9=B6=E5=AE=8C=E5=96=84=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E5=AE=9E=E4=BD=93=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将 application-local.yml 和 application-pre.yml 中 mybatis-plus 的 map-underscore-to-camel-case 设置为 true
- 在 StringUtil 类中新增 camelToSnakeCase 方法用于驼峰转下划线命名
- 更新 camelToKebabCase 方法注释并修正转换逻辑
- 为 User 实体类添加 @TableId 注解配置自增主键
---
src/main/resources/application-local.yml | 93 -----------------------
src/main/resources/application-pre.yml | 96 ------------------------
2 files changed, 189 deletions(-)
delete mode 100644 src/main/resources/application-local.yml
delete mode 100644 src/main/resources/application-pre.yml
diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml
deleted file mode 100644
index 64c3783..0000000
--- a/src/main/resources/application-local.yml
+++ /dev/null
@@ -1,93 +0,0 @@
-spring:
- servlet:
- multipart:
- max-file-size: 20MB
- max-request-size: 20MB
- jackson:
- date-format: yyyy-MM-dd HH:mm:ss
- time-zone: GMT+8
- serialization:
- WRITE_DATES_AS_TIMESTAMPS: false
- FAIL_ON_EMPTY_BEANS: false
- datasource:
- dynamic:
- primary: master
- strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
- hikari:
- maximum-pool-size: 4
- minimum-idle: 4
- leak-detection-threshold: 0
- connection-init-sql: SELECT 1
- connection-test-query: SELECT 1
- datasource:
- master: #${SERVER_ADDRESS}
- url: jdbc:mysql://localhost:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
- username:
- password:
- driver-class-name: com.mysql.cj.jdbc.Driver
- slave:
- url: jdbc:mysql://localhost:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
- username:
- password:
- driver-class-name: com.mysql.cj.jdbc.Driver
-
- data:
- redis:
- port: 6379
- host: localhost
- password:
- timeout: 5000
- lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
- pool:
- maxActive: 5000
- maxIdle: 30
- minIdle: 5
- max-wait: 2000
- time-between-eviction-runs: 60s
- cluster:
- refresh:
- adaptive: true
- period: 60s
-
-global:
- rsaPublicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC_F5UQC1QWsu3QsESQBz9M-GDA9Atm0qVSvwIsy568lyRLi-nq3VvvnmgrlL4yTbngFzyfb2Dn35cNCHsBvIaGuCY3_PpzPqMzVpxr2QlEkhEX9atnJQ1rWexS8QeZtPjpiIwoQrChTzXjD_sYUkDrqSykFplyivf0NSO2WqCBdwIDAQAB
- rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL8XlRALVBay7dCwRJAHP0z4YMD0C2bSpVK_AizLnryXJEuL6erdW--eaCuUvjJNueAXPJ9vYOfflw0IewG8hoa4Jjf8-nM-ozNWnGvZCUSSERf1q2clDWtZ7FLxB5m0-OmIjChCsKFPNeMP-xhSQOupLKQWmXKK9_Q1I7ZaoIF3AgMBAAECgYBxTUA61Ry0oL7U_86HP2TO9G4ZuhmQi9EucMaPXOPvmgYRLRIzCbDbMKc_P-BN3zwYnG57cgSZNz9OoPqeGvP_oVTnkoEpVkCSV-JP2p_DK09LdbDqszJXMrxAkPmWGUw8IRMcTJT1xJJcgzFE6T0CmTo-Vk47AnmqfJD4U6o74QJBAPRjVUJKZnrMSnSqKPDL2ThgTo8h7-KFxl_Z-g724lTOFiCmBpi6nCWAcuacFRrrYqxF-r9c4zdIyR7AvLROql8CQQDIK_kRF52dVtwShciZhyeUBLoi0nWV9F8mMGt60NTEER9zPEgPsv2aVn8h97KMWOwmd2Da4EPm25QxOuaKQC_pAkBczcfXp5co9KElkmR_pHl1jiTm97U3qSM-zPDHc_tYxvXiKgoBP4QCPbfkWMsu8MoEr4Jb3vMt0EcHlZtTQTgzAkAfmNla-lhV4sUgY1_T5EK6GbjsED6hag6u74u3ukkrnexR-10ApWdkumydBwV3I_464DM4uZfeVCDjWIHVpuYpAkEA6QLPztGD4V8Q1PqTEeSF3i68CKPM8vO1_mCH2JD7qsqDQcIKkczj5rTg7hlOKwB9V6gSw4CbnOF6moTooRD-cQ
-
-springdoc:
- api-docs:
- path: /v3/api-docs # 自定义 API 文档路径
- swagger-ui:
- path: /swagger-ui.html # 自定义 Swagger UI 路径
- enabled: true
- info:
- title: 文撩 API 文档
- description: 这是文撩平台的 API 文档
- version: v1.0
-
-mybatis-plus:
- configuration:
- map-underscore-to-camel-case: true
- auto-mapping-behavior: full
- #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
- mapper-locations: classpath*:mapper/**/*Mapper.xml
- global-config:
- # 逻辑删除配置
- db-config:
- update-strategy: IGNORED
- # 删除前
- logic-not-delete-value: 1
- # 删除后
- logic-delete-value: 0
-
-# 参考文章 https://zhuanlan.zhihu.com/p/145359625
-management:
- health:
- elasticsearch: #禁用健康检查
- enabled: false
- endpoints:
- web:
- exposure:
- include: "health"
- endpoint:
- health:
- show-details: always
\ No newline at end of file
diff --git a/src/main/resources/application-pre.yml b/src/main/resources/application-pre.yml
deleted file mode 100644
index a911aa2..0000000
--- a/src/main/resources/application-pre.yml
+++ /dev/null
@@ -1,96 +0,0 @@
-spring:
- datasource:
- dynamic:
- primary: master
- strict: true #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
- hikari:
- minimum-idle: 4
- maximum-pool-size: 4
- connection-init-sql: SELECT 1
- connection-test-query: SELECT 1
- datasource:
- master: #${SERVER_ADDRESS}
- url: jdbc:mysql://${SERVER_ADDRESS}:3306/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
- username: ${MYSQL_NAME}
- password: ${MYSQL_PWD}
- driver-class-name: com.mysql.cj.jdbc.Driver
- slave:
- url: jdbc:mysql://${SERVER_ADDRESS}:3306/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
- username: ${MYSQL_NAME}
- password: ${MYSQL_PWD}
- driver-class-name: com.mysql.cj.jdbc.Driver
- data:
- redis:
- port: 6379 #Redis服务器连接的端口
- host: ${SERVER_ADDRESS} # Redis服务器的地址
- password: ${REDIS_PWD} # Redis服务器连接密码(默认为空)
- timeout: 5000 # 连接超时时间(毫秒)
- lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
- pool:
- maxActive: 5000 #最大连接数
- maxIdle: 30 #连接池最大空闲连接数.
- minIdle: 5 #连接池最小空闲连接数.
- max-wait: 2000 #从连接池中获取连接时的最大等待时间
- time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
- cluster:
- refresh:
- adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
- period: 60s #刷新redis集群状态周期时间
-
-global:
- rsaPublicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC_F5UQC1QWsu3QsESQBz9M-GDA9Atm0qVSvwIsy568lyRLi-nq3VvvnmgrlL4yTbngFzyfb2Dn35cNCHsBvIaGuCY3_PpzPqMzVpxr2QlEkhEX9atnJQ1rWexS8QeZtPjpiIwoQrChTzXjD_sYUkDrqSykFplyivf0NSO2WqCBdwIDAQAB
- rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL8XlRALVBay7dCwRJAHP0z4YMD0C2bSpVK_AizLnryXJEuL6erdW--eaCuUvjJNueAXPJ9vYOfflw0IewG8hoa4Jjf8-nM-ozNWnGvZCUSSERf1q2clDWtZ7FLxB5m0-OmIjChCsKFPNeMP-xhSQOupLKQWmXKK9_Q1I7ZaoIF3AgMBAAECgYBxTUA61Ry0oL7U_86HP2TO9G4ZuhmQi9EucMaPXOPvmgYRLRIzCbDbMKc_P-BN3zwYnG57cgSZNz9OoPqeGvP_oVTnkoEpVkCSV-JP2p_DK09LdbDqszJXMrxAkPmWGUw8IRMcTJT1xJJcgzFE6T0CmTo-Vk47AnmqfJD4U6o74QJBAPRjVUJKZnrMSnSqKPDL2ThgTo8h7-KFxl_Z-g724lTOFiCmBpi6nCWAcuacFRrrYqxF-r9c4zdIyR7AvLROql8CQQDIK_kRF52dVtwShciZhyeUBLoi0nWV9F8mMGt60NTEER9zPEgPsv2aVn8h97KMWOwmd2Da4EPm25QxOuaKQC_pAkBczcfXp5co9KElkmR_pHl1jiTm97U3qSM-zPDHc_tYxvXiKgoBP4QCPbfkWMsu8MoEr4Jb3vMt0EcHlZtTQTgzAkAfmNla-lhV4sUgY1_T5EK6GbjsED6hag6u74u3ukkrnexR-10ApWdkumydBwV3I_464DM4uZfeVCDjWIHVpuYpAkEA6QLPztGD4V8Q1PqTEeSF3i68CKPM8vO1_mCH2JD7qsqDQcIKkczj5rTg7hlOKwB9V6gSw4CbnOF6moTooRD-cQ
-
-elasticsearch:
- host: localhost
- port: 9200
- username: elastic
- password: bz5oF*MGy8pKL_I=7KxY #window系统本地启动 es8.x 重置密码命令:.\elasticsearch-reset-password -u elastic
-
-rocketmq:
- name-server: ${SERVER_ADDRESS}:9876
- producer:
- group: producer-group
- consumer:
- group: consumer-group
- enable-orderly: false
-
-springdoc:
- api-docs:
- path: /v3/api-docs # 自定义 API 文档路径
- swagger-ui:
- path: /swagger-ui.html # 自定义 Swagger UI 路径
- enabled: true
- info:
- title: 文撩 API 文档
- description: 这是文撩平台的 API 文档
- version: v1.0
-
-mybatis-plus:
- configuration:
- map-underscore-to-camel-case: true
- auto-mapping-behavior: full
- #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
- mapper-locations: classpath*:mapper/**/*Mapper.xml
- global-config:
- # 逻辑删除配置
- db-config:
- update-strategy: IGNORED
- # 删除前
- logic-not-delete-value: 1
- # 删除后
- logic-delete-value: 0
-
-# 参考文章 https://zhuanlan.zhihu.com/p/145359625
-management:
- health:
- elasticsearch: #禁用健康检查
- enabled: false
- endpoints:
- web:
- exposure:
- include: "health"
- endpoint:
- health:
- show-details: always
-
From 2b123df3cf8d2b31605e1d4ca50b3acf655f0459 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:48:47 +0800
Subject: [PATCH 6/7] =?UTF-8?q?feat(config):=20=E6=B7=BB=E5=8A=A0=E7=BB=9F?=
=?UTF-8?q?=E4=B8=80=E5=BC=82=E6=AD=A5=E7=BA=BF=E7=A8=8B=E6=B1=A0=E9=85=8D?=
=?UTF-8?q?=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 防止默认线程池因无界队列引发 OOM 问题
- 配置核心线程数为 10,最大线程数为 50
- 设置缓冲队列容量为 1000,避免任务堆积
- 配置空闲线程存活时间为 60 秒
- 采用 CallerRunsPolicy 拒绝策略保证任务不丢失
- 启用优雅停机配置等待任务完成
---
.../xf/basedemo/config/ThreadPoolConfig.java | 50 +++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 src/main/java/cn/xf/basedemo/config/ThreadPoolConfig.java
diff --git a/src/main/java/cn/xf/basedemo/config/ThreadPoolConfig.java b/src/main/java/cn/xf/basedemo/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..e8c5a4c
--- /dev/null
+++ b/src/main/java/cn/xf/basedemo/config/ThreadPoolConfig.java
@@ -0,0 +1,50 @@
+package cn.xf.basedemo.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @Description: 统一异步线程池配置类(防止默认线程池由于无界队列引发 OOM)
+ * @Author: xiongfeng
+ * @Date: 2026/5/28
+ * @Version: 1.0
+ */
+@Slf4j
+@Configuration
+@EnableAsync
+public class ThreadPoolConfig {
+
+ @Bean(name = "asyncServiceExecutor")
+ public Executor asyncServiceExecutor() {
+ log.info("初始化异步线程池 [asyncServiceExecutor] 开始...");
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+
+ // 核心线程数:根据 CPU 核心数与业务性质配置(此处设为 10)
+ executor.setCorePoolSize(10);
+ // 最大线程数:高并发时能够支持的最大线程数
+ executor.setMaxPoolSize(50);
+ // 缓冲队列容量:限制任务队列大小,防止无界队列堆积导致 OOM
+ executor.setQueueCapacity(1000);
+ // 空闲线程存活时间(秒)
+ executor.setKeepAliveSeconds(60);
+ // 线程名称前缀
+ executor.setThreadNamePrefix("async-executor-");
+
+ // 拒绝策略:当队列满且达到最大线程数时,由调用者线程直接执行任务(保证任务不丢失,同时降低提交速度)
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // 优雅停机配置
+ executor.setWaitForTasksToCompleteOnShutdown(true);
+ executor.setAwaitTerminationSeconds(60);
+
+ executor.initialize();
+ log.info("初始化异步线程池 [asyncServiceExecutor] 成功!");
+ return executor;
+ }
+}
From 39df5c5945d062c455662f086583dba1025d6b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=B7=E8=A8=80?= <2439534736@qq.com>
Date: Thu, 28 May 2026 15:50:58 +0800
Subject: [PATCH 7/7] =?UTF-8?q?chore(config):=20=E5=88=A0=E9=99=A4=20ELK?=
=?UTF-8?q?=20Docker=20Compose=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除 elasticsearch 服务配置(端口 9200)
- 移除 kibana 服务配置(端口 5601)
- 移除 logstash 服务配置(端口 4560)
- 清理相关容器挂载卷和依赖关系配置
---
.../resources/docker/elk_docker-compose.yml | 36 -------------------
.../resources/docker/logstash-springboot.conf | 14 --------
2 files changed, 50 deletions(-)
delete mode 100644 src/main/resources/docker/elk_docker-compose.yml
delete mode 100644 src/main/resources/docker/logstash-springboot.conf
diff --git a/src/main/resources/docker/elk_docker-compose.yml b/src/main/resources/docker/elk_docker-compose.yml
deleted file mode 100644
index 708c8ed..0000000
--- a/src/main/resources/docker/elk_docker-compose.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-version: '3'
-services:
- elasticsearch:
- image: elasticsearch:6.4.0
- container_name: elasticsearch
- environment:
- - "cluster.name=elasticsearch" #设置集群名称为elasticsearch
- - "discovery.type=single-node" #以单一节点模式启动
- - "ES_JAVA_OPTS=-Xms512m -Xmx512m" #设置使用jvm内存大小
- volumes:
- - /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载
- - /mydata/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载
- ports:
- - 9200:9200
- kibana:
- image: kibana:6.4.0
- container_name: kibana
- links:
- - elasticsearch:es #可以用es这个域名访问elasticsearch服务
- depends_on:
- - elasticsearch #kibana在elasticsearch启动之后再启动
- environment:
- - "elasticsearch.hosts=http://es:9200" #设置访问elasticsearch的地址
- ports:
- - 5601:5601
- logstash:
- image: logstash:6.4.0
- container_name: logstash
- volumes:
- - /mydata/logstash/logstash-springboot.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件
- depends_on:
- - elasticsearch #kibana在elasticsearch启动之后再启动
- links:
- - elasticsearch:es #可以用es这个域名访问elasticsearch服务
- ports:
- - 4560:4560
\ No newline at end of file
diff --git a/src/main/resources/docker/logstash-springboot.conf b/src/main/resources/docker/logstash-springboot.conf
deleted file mode 100644
index a71e919..0000000
--- a/src/main/resources/docker/logstash-springboot.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-input {
- tcp {
- mode => "server"
- host => "0.0.0.0"
- port => 4560
- codec => json_lines
- }
-}
-output {
- elasticsearch {
- hosts => "es:9200"
- index => "springboot-logstash-%{+YYYY.MM.dd}"
- }
-}
\ No newline at end of file