diff --git a/enlish-service/pom.xml b/enlish-service/pom.xml index 7d8a840..f8aeb28 100644 --- a/enlish-service/pom.xml +++ b/enlish-service/pom.xml @@ -58,6 +58,23 @@ mysql-connector-java + + com.alibaba + transmittable-thread-local + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + diff --git a/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/RedisTemplateConfig.java b/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/RedisTemplateConfig.java new file mode 100644 index 0000000..9dec5e8 --- /dev/null +++ b/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/RedisTemplateConfig.java @@ -0,0 +1,32 @@ +package com.yinlihupo.enlish.service.config; + +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.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +public class RedisTemplateConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 设置 RedisTemplate 的连接工厂 + redisTemplate.setConnectionFactory(connectionFactory); + + // 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key 值,确保 key 是可读的字符串 + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + + // 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值, 确保存储的是 JSON 格式 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + redisTemplate.setValueSerializer(serializer); + redisTemplate.setHashValueSerializer(serializer); + + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } +} diff --git a/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/ThreadPoolConfig.java b/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/ThreadPoolConfig.java new file mode 100644 index 0000000..6c1cbd8 --- /dev/null +++ b/enlish-service/src/main/java/com/yinlihupo/enlish/service/config/ThreadPoolConfig.java @@ -0,0 +1,39 @@ +package com.yinlihupo.enlish.service.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + + +@Configuration +public class ThreadPoolConfig { + + @Bean(name = "taskExecutor") + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + // 核心线程数 + executor.setCorePoolSize(10); + // 最大线程数 + executor.setMaxPoolSize(50); + // 队列容量 + executor.setQueueCapacity(200); + // 线程活跃时间(秒) + executor.setKeepAliveSeconds(30); + // 线程名前缀 + executor.setThreadNamePrefix("AuthExecutor-"); + + // 拒绝策略:由调用线程处理(一般为主线程) + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + + // 等待所有任务结束后再关闭线程池 + executor.setWaitForTasksToCompleteOnShutdown(true); + // 设置等待时间,如果超过这个时间还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是被没有完成的任务阻塞 + executor.setAwaitTerminationSeconds(60); + + executor.initialize(); + return executor; + } +} diff --git a/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/LoginTypeEnum.java b/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/LoginTypeEnum.java new file mode 100644 index 0000000..cf5377d --- /dev/null +++ b/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/LoginTypeEnum.java @@ -0,0 +1,28 @@ +package com.yinlihupo.enlish.service.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Objects; + + +@Getter +@AllArgsConstructor +public enum LoginTypeEnum { + // 验证码 + VERIFICATION_CODE(1), + // 密码 + PASSWORD(2); + + private final Integer value; + + public static LoginTypeEnum valueOf(Integer code) { + for (LoginTypeEnum loginTypeEnum : LoginTypeEnum.values()) { + if (Objects.equals(code, loginTypeEnum.getValue())) { + return loginTypeEnum; + } + } + return null; + } + +} diff --git a/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/ResponseCodeEnum.java b/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/ResponseCodeEnum.java new file mode 100644 index 0000000..f8f8f7a --- /dev/null +++ b/enlish-service/src/main/java/com/yinlihupo/enlish/service/enums/ResponseCodeEnum.java @@ -0,0 +1,26 @@ +package com.yinlihupo.enlish.service.enums; + + +import com.yinlihupo.framework.common.exception.BaseExceptionInterface; +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@Getter +@AllArgsConstructor +public enum ResponseCodeEnum implements BaseExceptionInterface { + + // ----------- 通用异常状态码 ----------- + SYSTEM_ERROR("AUTH-10000", "出错啦,后台小哥正在努力修复中..."), + PARAM_NOT_VALID("AUTH-10001", "参数错误"), + + // ----------- 业务异常状态码 ----------- + + ; + + // 异常码 + private final String errorCode; + // 错误信息 + private final String errorMessage; + +} diff --git a/enlish-service/src/main/java/com/yinlihupo/enlish/service/exception/GlobalExceptionHandler.java b/enlish-service/src/main/java/com/yinlihupo/enlish/service/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..4c00734 --- /dev/null +++ b/enlish-service/src/main/java/com/yinlihupo/enlish/service/exception/GlobalExceptionHandler.java @@ -0,0 +1,99 @@ +package com.yinlihupo.enlish.service.exception; + + +import com.yinlihupo.enlish.service.enums.ResponseCodeEnum; +import com.yinlihupo.framework.common.exception.BizException; +import com.yinlihupo.framework.common.response.Response; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Optional; + + +@ControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + /** + * 捕获自定义业务异常 + * @return + */ + @ExceptionHandler({ BizException.class }) + @ResponseBody + public Response handleBizException(HttpServletRequest request, BizException e) { + log.warn("{} request fail, errorCode: {}, errorMessage: {}", request.getRequestURI(), e.getErrorCode(), e.getErrorMessage()); + return Response.fail(e); + } + + /** + * 捕获参数校验异常 + * @return + */ + @ExceptionHandler({ MethodArgumentNotValidException.class }) + @ResponseBody + public Response handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) { + // 参数错误异常码 + String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(); + + // 获取 BindingResult + BindingResult bindingResult = e.getBindingResult(); + + StringBuilder sb = new StringBuilder(); + + // 获取校验不通过的字段,并组合错误信息,格式为: email 邮箱格式不正确, 当前值: '123124qq.com'; + Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> { + errors.forEach(error -> + sb.append(error.getField()) + .append(" ") + .append(error.getDefaultMessage()) + .append(", 当前值: '") + .append(error.getRejectedValue()) + .append("'; ") + + ); + }); + + // 错误信息 + String errorMessage = sb.toString(); + + log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage); + + return Response.fail(errorCode, errorMessage); + } + + /** + * 捕获 guava 参数校验异常 + * @return + */ + @ExceptionHandler({ IllegalArgumentException.class }) + @ResponseBody + public Response handleIllegalArgumentException(HttpServletRequest request, IllegalArgumentException e) { + // 参数错误异常码 + String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(); + + // 错误信息 + String errorMessage = e.getMessage(); + + log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage); + + return Response.fail(errorCode, errorMessage); + } + + /** + * 其他类型异常 + * @param request + * @param e + * @return + */ + @ExceptionHandler({ Exception.class }) + @ResponseBody + public Response handleOtherException(HttpServletRequest request, Exception e) { + log.error("{} request error, ", request.getRequestURI(), e); + return Response.fail(ResponseCodeEnum.SYSTEM_ERROR); + } +} diff --git a/enlish-service/src/main/resources/config/application-dev.yml b/enlish-service/src/main/resources/config/application-dev.yml index d9778f7..dfbd476 100644 --- a/enlish-service/src/main/resources/config/application-dev.yml +++ b/enlish-service/src/main/resources/config/application-dev.yml @@ -5,3 +5,17 @@ spring: url: jdbc:mysql://124.220.58.5:3306/enlish username: root # 数据库用户名 password: YLHP@admin123 # 数据库密码 + data: + redis: + database: 6 # Redis 数据库索引(默认为 0) + host: 124.220.58.5 # Redis 服务器地址 + port: 6543 # Redis 服务器连接端口 + password: 741963 # Redis 服务器连接密码(默认为空) + timeout: 5s # 读超时时间 + connect-timeout: 5s # 链接超时时间 + lettuce: + pool: + max-active: 200 # 连接池最大连接数 + max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) + min-idle: 0 # 连接池中的最小空闲连接 + max-idle: 10 # 连接池中的最大空闲连接