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 822dca3..5dfd7a3 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,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/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; - } - -} 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 5351862..61b2261 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; @@ -61,9 +63,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()); } /** @@ -71,9 +73,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()); } /** @@ -81,7 +83,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(); @@ -97,7 +99,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); } /** @@ -105,9 +107,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/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/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; + } +} diff --git a/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java b/src/main/java/cn/xf/basedemo/interceptor/TokenInterceptor.java new file mode 100644 index 0000000..e69de29 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/java/cn/xf/basedemo/service/impl/UserServiceImpl.java b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java index 33aee7e..129d7f1 100644 --- a/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java +++ b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java @@ -18,6 +18,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; @@ -47,10 +48,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 = ""; @@ -67,15 +70,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/application-local.yml b/src/main/resources/application-local.yml deleted file mode 100644 index 1964d39..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: false - 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 a172ef3..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: false - 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 - 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/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 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 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}"} + + + + + + + + + + + + + + + + + + + + + +