commit fe12d54c92fe4ab28f5bbb0b7d7f8d8bd33e153c Author: Hanserwei Date: Sun Sep 28 14:42:39 2025 +0800 han-note项目初始化完毕! - 整合完毕MyBatis-Plus - 整合Druid数据库链接池 - 自定义两个Starter,业务日志打印Starter和自定义Jackson配置类,支持Java8的LocalTime等API - 整合 flatten-maven-plugin 插件:解决子模块单独打包失败问题 diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..5c08283 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### 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 +/.idea/ +/han-note-auth/src/main/resources/application-dev.yml +/han-note-auth/src/main/resources/application-prod.yml +/han-note-auth/logs/ +/logs/ +/.idea/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100755 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100755 index 0000000..c1997d2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100755 index 0000000..f281ec3 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100755 index 0000000..1c5170e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100755 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/han-note-auth/.mvn/wrapper/maven-wrapper.properties b/han-note-auth/.mvn/wrapper/maven-wrapper.properties new file mode 100755 index 0000000..c0bcafe --- /dev/null +++ b/han-note-auth/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip diff --git a/han-note-auth/pom.xml b/han-note-auth/pom.xml new file mode 100755 index 0000000..85faf5d --- /dev/null +++ b/han-note-auth/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.hanserwei + han-note + ${revision} + + han-note-auth + ${project.artifactId} + 小憨书:认证服务(负责处理用户登录、注册、账号注销等) + jar + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.hanserwei + hanserwei-spring-boot-starter-biz-operationlog + + + com.mysql + mysql-connector-j + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + com.alibaba + druid-spring-boot-3-starter + + + com.hanserwei + hanserwei-spring-boot-starter-jackson + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/han-note-auth/src/main/java/com/hanserwei/hannote/auth/HanNoteAuthApplication.java b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/HanNoteAuthApplication.java new file mode 100755 index 0000000..846cb53 --- /dev/null +++ b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/HanNoteAuthApplication.java @@ -0,0 +1,15 @@ +package com.hanserwei.hannote.auth; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.hanserwei.hannote.auth.domain.mapper") +public class HanNoteAuthApplication { + + public static void main(String[] args) { + SpringApplication.run(HanNoteAuthApplication.class, args); + } + +} diff --git a/han-note-auth/src/main/java/com/hanserwei/hannote/auth/enums/ResponseCodeEnum.java b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/enums/ResponseCodeEnum.java new file mode 100644 index 0000000..1b377d2 --- /dev/null +++ b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/enums/ResponseCodeEnum.java @@ -0,0 +1,24 @@ +package com.hanserwei.hannote.auth.enums; + +import com.hanserwei.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 errorMsg; + +} + diff --git a/han-note-auth/src/main/java/com/hanserwei/hannote/auth/exception/GlobalExceptionHandler.java b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..eec386e --- /dev/null +++ b/han-note-auth/src/main/java/com/hanserwei/hannote/auth/exception/GlobalExceptionHandler.java @@ -0,0 +1,83 @@ +package com.hanserwei.hannote.auth.exception; + +import com.hanserwei.framework.common.exception.ApiException; +import com.hanserwei.framework.common.response.Response; +import com.hanserwei.hannote.auth.enums.ResponseCodeEnum; +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 Response.fail(e) + */ + @ExceptionHandler({ApiException.class}) + @ResponseBody + public Response handleApiException(HttpServletRequest request, ApiException e) { + log.warn("{} request fail, errorCode: {}, errorMessage: {}", request.getRequestURI(), e.getErrorCode(), e.getErrorMsg()); + return Response.fail(e); + } + + /** + * 捕获参数校验异常 + * + * @return Response.fail(errorCode, errorMessage) + */ + @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.of(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); + } + + /** + * 其他类型异常 + * + * @param request 请求 + * @param e 异常 + * @return Response.fail(ResponseCodeEnum.SYSTEM_ERROR) + */ + @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/han-note-auth/src/main/resources/application.yml b/han-note-auth/src/main/resources/application.yml new file mode 100755 index 0000000..2c319f9 --- /dev/null +++ b/han-note-auth/src/main/resources/application.yml @@ -0,0 +1,23 @@ +spring: + application: + name: han-note-auth + profiles: + active: dev # 默认激活 dev 本地开发环境 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver # 指定数据库驱动类 + # 数据库连接信息 + url: ${spring.datasource.url} + username: ${spring.datasource.username} # 数据库用户名 + password: ${spring.datasource.password} # 数据库密码 +server: + port: 8080 # 项目启动的端口 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl + global-config: + banner: false + mapper-locations: classpath*:/mapperxml/*.xml +logging: + level: + com.hanserwei.hannote.auth.domain.mapper: debug diff --git a/han-note-auth/src/main/resources/logback-spring.xml b/han-note-auth/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..ced2931 --- /dev/null +++ b/han-note-auth/src/main/resources/logback-spring.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + ${LOG_FILE}-%i.log + + 30 + + 10MB + + 0 + + false + + + ${LOG_PATTERN} + UTF-8 + + + + + + + 0 + + 256 + + + + + + + + + + + + + + + + + + + + + diff --git a/han-note-auth/src/test/java/com/hanserwei/hannote/auth/DruidTests.java b/han-note-auth/src/test/java/com/hanserwei/hannote/auth/DruidTests.java new file mode 100644 index 0000000..cc17864 --- /dev/null +++ b/han-note-auth/src/test/java/com/hanserwei/hannote/auth/DruidTests.java @@ -0,0 +1,34 @@ +package com.hanserwei.hannote.auth; + +import com.alibaba.druid.filter.config.ConfigTools; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Slf4j +class DruidTests { + + + /** + * Druid 密码加密 + */ + @Test + @SneakyThrows + void testEncodePassword() { + // 你的密码 + String password = "mysql"; + String[] arr = ConfigTools.genKeyPair(512); + + // 私钥 + log.info("privateKey: {}", arr[0]); + // 公钥 + log.info("publicKey: {}", arr[1]); + + // 通过私钥加密密码 + String encodePassword = ConfigTools.encrypt(arr[0], password); + log.info("password: {}", encodePassword); + } + +} \ No newline at end of file diff --git a/han-note-auth/src/test/java/com/hanserwei/hannote/auth/HanNoteAuthApplicationTests.java b/han-note-auth/src/test/java/com/hanserwei/hannote/auth/HanNoteAuthApplicationTests.java new file mode 100755 index 0000000..3586e33 --- /dev/null +++ b/han-note-auth/src/test/java/com/hanserwei/hannote/auth/HanNoteAuthApplicationTests.java @@ -0,0 +1,14 @@ +package com.hanserwei.hannote.auth; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Slf4j +class HanNoteAuthApplicationTests { + + + +} + diff --git a/hanserwei-framework/hanserwei-common/pom.xml b/hanserwei-framework/hanserwei-common/pom.xml new file mode 100755 index 0000000..53dfaf1 --- /dev/null +++ b/hanserwei-framework/hanserwei-common/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + + com.hanserwei + hanserwei-framework + ${revision} + + + hanserwei-common + jar + 平台通用模块,如一些通用枚举、工具类等等 + hanserwei-common + + + UTF-8 + + + + + org.projectlombok + lombok + + + + com.fasterxml.jackson.core + jackson-databind + + + + com.fasterxml.jackson.core + jackson-core + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + jakarta.validation + jakarta.validation-api + + + org.hibernate.validator + hibernate-validator + + + diff --git a/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/constant/DateConstants.java b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/constant/DateConstants.java new file mode 100755 index 0000000..f9ad973 --- /dev/null +++ b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/constant/DateConstants.java @@ -0,0 +1,26 @@ +package com.hanserwei.framework.common.constant; + +import java.time.format.DateTimeFormatter; + +public interface DateConstants { + + /** + * DateTimeFormatter:年-月-日 时:分:秒 + */ + DateTimeFormatter DATE_FORMAT_Y_M_D_H_M_S = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + /** + * DateTimeFormatter:年-月-日 + */ + DateTimeFormatter DATE_FORMAT_Y_M_D = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + /** + * DateTimeFormatter:时:分:秒 + */ + DateTimeFormatter DATE_FORMAT_H_M_S = DateTimeFormatter.ofPattern("HH:mm:ss"); + + /** + * DateTimeFormatter:年-月 + */ + DateTimeFormatter DATE_FORMAT_Y_M = DateTimeFormatter.ofPattern("yyyy-MM"); +} diff --git a/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/ApiException.java b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/ApiException.java new file mode 100755 index 0000000..ccdb728 --- /dev/null +++ b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/ApiException.java @@ -0,0 +1,18 @@ +package com.hanserwei.framework.common.exception; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ApiException extends RuntimeException { + // 异常码 + private String errorCode; + // 异常信息 + private String errorMsg; + + public ApiException(BaseExceptionInterface baseExceptionInterface) { + this.errorCode = baseExceptionInterface.getErrorCode(); + this.errorMsg = baseExceptionInterface.getErrorMsg(); + } +} diff --git a/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/BaseExceptionInterface.java b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/BaseExceptionInterface.java new file mode 100755 index 0000000..aa9c1b7 --- /dev/null +++ b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/exception/BaseExceptionInterface.java @@ -0,0 +1,10 @@ +package com.hanserwei.framework.common.exception; + +public interface BaseExceptionInterface { + + // 获取异常码 + String getErrorCode(); + + // 获取异常信息 + String getErrorMsg(); +} diff --git a/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/response/Response.java b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/response/Response.java new file mode 100755 index 0000000..a984afc --- /dev/null +++ b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/response/Response.java @@ -0,0 +1,70 @@ +package com.hanserwei.framework.common.response; + +import com.hanserwei.framework.common.exception.ApiException; +import com.hanserwei.framework.common.exception.BaseExceptionInterface; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class Response implements Serializable { + + // 是否成功,默认为 true + private boolean success = true; + // 响应消息 + private String message; + // 异常码 + private String errorCode; + // 响应数据 + private T data; + + // =================================== 成功响应 =================================== + public static Response success() { + return new Response<>(); + } + + public static Response success(T data) { + Response response = new Response<>(); + response.setData(data); + return response; + } + + // =================================== 失败响应 =================================== + public static Response fail() { + Response response = new Response<>(); + response.setSuccess(false); + return response; + } + + public static Response fail(String errorMessage) { + Response response = new Response<>(); + response.setSuccess(false); + response.setMessage(errorMessage); + return response; + } + + public static Response fail(String errorCode, String errorMessage) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(errorCode); + response.setMessage(errorMessage); + return response; + } + + public static Response fail(ApiException apiException) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(apiException.getErrorCode()); + response.setMessage(apiException.getErrorMsg()); + return response; + } + + public static Response fail(BaseExceptionInterface baseExceptionInterface) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(baseExceptionInterface.getErrorCode()); + response.setMessage(baseExceptionInterface.getErrorMsg()); + return response; + } + +} diff --git a/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/utils/JsonUtils.java b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/utils/JsonUtils.java new file mode 100755 index 0000000..2edbf57 --- /dev/null +++ b/hanserwei-framework/hanserwei-common/src/main/java/com/hanserwei/framework/common/utils/JsonUtils.java @@ -0,0 +1,36 @@ +package com.hanserwei.framework.common.utils; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.SneakyThrows; + +public class JsonUtils { + private static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + OBJECT_MAPPER.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化问题 + } + + /** + * 初始化:统一使用 Spring Boot 个性化配置的 ObjectMapper + */ + public static void init(ObjectMapper objectMapper) { + OBJECT_MAPPER = objectMapper; + } + + + /** + * 将对象转换为 JSON 字符串 + * + * @param obj 待转换的对象 + * @return JSON 字符串 + */ + @SneakyThrows + public static String toJsonString(Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } +} diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/pom.xml b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/pom.xml new file mode 100755 index 0000000..905fbb4 --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + + com.hanserwei + hanserwei-framework + ${revision} + + + jar + + hanserwei-spring-boot-starter-biz-operationlog + ${project.artifactId} + 接口日志组件 + + + UTF-8 + + + + + com.hanserwei + hanserwei-common + + + + org.springframework.boot + spring-boot-starter-aop + + + diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLog.java b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLog.java new file mode 100755 index 0000000..b9ba8ce --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLog.java @@ -0,0 +1,15 @@ +package com.hanserwei.framework.biz.operationlog.aspect; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Documented +public @interface ApiOperationLog { + /** + * API 功能描述 + * + * @return API 功能描述 + */ + String description() default ""; +} diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLogAspect.java b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLogAspect.java new file mode 100755 index 0000000..8834bb6 --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/aspect/ApiOperationLogAspect.java @@ -0,0 +1,97 @@ +package com.hanserwei.framework.biz.operationlog.aspect; + +import com.hanserwei.framework.common.utils.JsonUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Aspect +@Slf4j +public class ApiOperationLogAspect { + + /** + * 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 + */ + @Pointcut("@annotation(com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog)") + public void apiOperationLog() { + } + + /** + * 环绕 + * + * @param joinPoint 切入点 + * @return 方法执行结果 + * @throws Throwable 抛出异常 + */ + @Around("apiOperationLog()") + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { + // 请求开始时间 + long startTime = System.currentTimeMillis(); + + // 获取被请求的类和方法 + String className = joinPoint.getTarget().getClass().getSimpleName(); + String methodName = joinPoint.getSignature().getName(); + + // 请求入参 + Object[] args = joinPoint.getArgs(); + // 入参转 JSON 字符串 + String argsJsonStr = Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(", ")); + + // 功能描述信息 + String description = getApiOperationLogDescription(joinPoint); + + // 打印请求相关参数 + log.info("====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== ", + description, argsJsonStr, className, methodName); + + // 执行切点方法 + Object result = joinPoint.proceed(); + + // 执行耗时 + long executionTime = System.currentTimeMillis() - startTime; + + // 打印出参等相关信息 + log.info("====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== ", + description, executionTime, JsonUtils.toJsonString(result)); + + return result; + } + + /** + * 获取注解的描述信息 + * + * @param joinPoint 切点 + * @return 描述信息 + */ + private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) { + // 1. 从 ProceedingJoinPoint 获取 MethodSignature + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + + // 2. 使用 MethodSignature 获取当前被注解的 Method + Method method = signature.getMethod(); + + // 3. 从 Method 中提取 LogExecution 注解 + ApiOperationLog apiOperationLog = method.getAnnotation(ApiOperationLog.class); + + // 4. 从 LogExecution 注解中获取 description 属性 + return apiOperationLog.description(); + } + + /** + * 转 JSON 字符串 + * + * @return Function + */ + private Function toJsonStr() { + return JsonUtils::toJsonString; + } + +} diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/config/ApiOperationLogAutoConfiguration.java b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/config/ApiOperationLogAutoConfiguration.java new file mode 100755 index 0000000..a8b70c0 --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/java/com/hanserwei/framework/biz/operationlog/config/ApiOperationLogAutoConfiguration.java @@ -0,0 +1,14 @@ +package com.hanserwei.framework.biz.operationlog.config; + +import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLogAspect; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; + +@AutoConfiguration +public class ApiOperationLogAutoConfiguration { + + @Bean + public ApiOperationLogAspect apiOperationLogAspect() { + return new ApiOperationLogAspect(); + } +} diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100755 index 0000000..4a08fd8 --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-operationlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.hanserwei.framework.biz.operationlog.config.ApiOperationLogAutoConfiguration \ No newline at end of file diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-jackson/pom.xml b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/pom.xml new file mode 100644 index 0000000..b6b417a --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + com.hanserwei + hanserwei-framework + ${revision} + + + jar + + hanserwei-spring-boot-starter-jackson + ${project.artifactId} + 小憨书自定义jackson配置类 + + + UTF-8 + + + + + com.hanserwei + hanserwei-common + + + org.springframework.boot + spring-boot-autoconfigure + + + diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/java/com/hanserwei/customjackson/config/CustomJacksonConfiguration.java b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/java/com/hanserwei/customjackson/config/CustomJacksonConfiguration.java new file mode 100644 index 0000000..29a8a6d --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/java/com/hanserwei/customjackson/config/CustomJacksonConfiguration.java @@ -0,0 +1,63 @@ +package com.hanserwei.customjackson.config; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.YearMonthDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.YearMonthSerializer; +import com.hanserwei.framework.common.constant.DateConstants; +import com.hanserwei.framework.common.utils.JsonUtils; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.YearMonth; +import java.util.TimeZone; + +@AutoConfiguration +public class CustomJacksonConfiguration { + + @Bean + public ObjectMapper objectMapper() { + // 初始化一个 ObjectMapper 对象,用于自定义 Jackson 的行为 + ObjectMapper objectMapper = new ObjectMapper(); + + // 忽略未知属性 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + + // 设置凡是为 null 的字段,返参中均不返回,请根据项目组约定是否开启 + // objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + // 设置时区 + objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + + // JavaTimeModule 用于指定序列化和反序列化规则 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + + // 支持 LocalDateTime、LocalDate、LocalTime + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateConstants.DATE_FORMAT_Y_M_D_H_M_S)); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateConstants.DATE_FORMAT_Y_M_D_H_M_S)); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateConstants.DATE_FORMAT_Y_M_D)); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateConstants.DATE_FORMAT_Y_M_D)); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateConstants.DATE_FORMAT_H_M_S)); + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateConstants.DATE_FORMAT_H_M_S)); + // 支持 YearMonth + javaTimeModule.addSerializer(YearMonth.class, new YearMonthSerializer(DateConstants.DATE_FORMAT_Y_M)); + javaTimeModule.addDeserializer(YearMonth.class, new YearMonthDeserializer(DateConstants.DATE_FORMAT_Y_M)); + + objectMapper.registerModule(javaTimeModule); + JsonUtils.init(objectMapper); + + return objectMapper; + } +} diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100755 index 0000000..5f20794 --- /dev/null +++ b/hanserwei-framework/hanserwei-spring-boot-starter-jackson/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.hanserwei.customjackson.config.CustomJacksonConfiguration \ No newline at end of file diff --git a/hanserwei-framework/pom.xml b/hanserwei-framework/pom.xml new file mode 100755 index 0000000..f6fb978 --- /dev/null +++ b/hanserwei-framework/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + com.hanserwei + han-note + ${revision} + + + hanserwei-common + hanserwei-spring-boot-starter-biz-operationlog + hanserwei-spring-boot-starter-jackson + + + pom + + hanserwei-framework + ${project.artifactId} + 平台基础设施层:封装一些常用功能,供各个业务线拿来即用 + + + UTF-8 + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..a1fae68 --- /dev/null +++ b/pom.xml @@ -0,0 +1,192 @@ + + 4.0.0 + + com.hanserwei + han-note + ${revision} + pom + + ${project.artifactId} + 小憨书(仿小红书),基于 Spring Cloud Alibaba 微服务架构 + + + han-note-auth + hanserwei-framework + + + + + 0.0.1-SNAPSHOT + + 21 + ${java.version} + ${java.version} + + UTF-8 + + 3.8.1 + 1.7.3 + + 1.18.30 + 3.2.4 + 2023.0.1.0 + 2023.0.1 + 2.15.4 + 3.5.14 + 8.4.0 + 1.2.27 + + + + + + org.projectlombok + lombok + ${lombok.version} + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + com.hanserwei + hanserwei-common + ${revision} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + + com.hanserwei + hanserwei-spring-boot-starter-biz-operationlog + ${revision} + + + com.hanserwei + hanserwei-spring-boot-starter-jackson + ${revision} + + + com.baomidou + mybatis-plus-bom + ${mybatis-plus.version} + pom + import + + + com.mysql + mysql-connector-j + ${mysql-connector-j.version} + + + com.alibaba + druid-spring-boot-3-starter + ${druid.version} + + + + + + + junit + junit + 3.8.1 + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + repackage + + repackage + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + + + + org.codehaus.mojo + flatten-maven-plugin + ${flatten-maven-plugin.version} + + resolveCiFriendliesOnly + true + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + + + +