日志切面组件
This commit is contained in:
+3
-6
@@ -5,10 +5,7 @@ target/
|
|||||||
.kotlin
|
.kotlin
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
.idea/modules.xml
|
.idea
|
||||||
.idea/jarRepositories.xml
|
|
||||||
.idea/compiler.xml
|
|
||||||
.idea/libraries/
|
|
||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
@@ -18,7 +15,6 @@ target/
|
|||||||
.classpath
|
.classpath
|
||||||
.factorypath
|
.factorypath
|
||||||
.project
|
.project
|
||||||
.settings
|
|
||||||
.springBeans
|
.springBeans
|
||||||
.sts4-cache
|
.sts4-cache
|
||||||
|
|
||||||
@@ -34,4 +30,5 @@ build/
|
|||||||
|
|
||||||
|
|
||||||
### Mac OS ###
|
### Mac OS ###
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/.idea/
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=UTF-8
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
activeProfiles=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
resolveWorkspaceProjects=true
|
||||||
|
version=1
|
||||||
Vendored
+3
@@ -376,5 +376,8 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_parameter_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_method_return_type" value="insert"/>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
Vendored
+3
-2
@@ -7,6 +7,7 @@
|
|||||||
"editor.accessibilitySupport": "auto",
|
"editor.accessibilitySupport": "auto",
|
||||||
"editor.fontFamily": "JetBrains Mono",
|
"editor.fontFamily": "JetBrains Mono",
|
||||||
"java.compile.nullAnalysis.mode": "automatic",
|
"java.compile.nullAnalysis.mode": "automatic",
|
||||||
"java.configuration.updateBuildConfiguration": "interactive",
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
"java.format.settings.url": ".vscode/java-formatter.xml"
|
"java.format.settings.url": ".vscode/java-formatter.xml",
|
||||||
|
"commentTranslate.targetLanguage": "zh-CN"
|
||||||
}
|
}
|
||||||
@@ -38,11 +38,23 @@
|
|||||||
<spring-boot.version>3.0.2</spring-boot.version>
|
<spring-boot.version>3.0.2</spring-boot.version>
|
||||||
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
|
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
|
||||||
<spring-cloud.version>2022.0.0</spring-cloud.version>
|
<spring-cloud.version>2022.0.0</spring-cloud.version>
|
||||||
|
<jackson.version>2.16.1</jackson.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-common</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 业务接口日志组件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-spring-boot-starter-biz-operationlog</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<!-- Spring Boot 官方依赖管理 -->
|
<!-- Spring Boot 官方依赖管理 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -77,6 +89,18 @@
|
|||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Jackson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-core</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,15 @@
|
|||||||
<description>小壹书:认证服务(负责处理用户登录、注册、账号注销等)</description>
|
<description>小壹书:认证服务(负责处理用户登录、注册、账号注销等)</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 业务接口日志组件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-spring-boot-starter-biz-operationlog</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package top.crushtj.xiaoyishu.auth.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||||
|
import top.crushtj.framework.common.response.Response;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @Title: TestController
|
||||||
|
* @Description: 测试控制器
|
||||||
|
* @Author: ayi
|
||||||
|
* @Date: 2025/11/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class TestController {
|
||||||
|
|
||||||
|
@GetMapping("/test")
|
||||||
|
@ApiOperationLog(description = "测试接口")
|
||||||
|
public Response<String> testController() {
|
||||||
|
return Response.success("Hello World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: xiaoyi-auth
|
||||||
|
output:
|
||||||
|
ansi:
|
||||||
|
enabled: always
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
spring:
|
spring:
|
||||||
application:
|
profiles:
|
||||||
name: xiaoyi-auth
|
active:
|
||||||
output:
|
- dev
|
||||||
ansi:
|
|
||||||
enabled: always
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>xiaoyi-common</module>
|
<module>xiaoyi-common</module>
|
||||||
|
<module>xiaoyi-spring-boot-starter-biz-operationlog</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -20,6 +20,22 @@
|
|||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Jackson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 解决 Jackson Java 8 新日期 API 的序列化问题 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package top.crushtj.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @Title: JsonUtils
|
||||||
|
* @Description: JSON 工具类
|
||||||
|
* @Author: ayi
|
||||||
|
* @Date: 2025/11/21
|
||||||
|
*/
|
||||||
|
public class JsonUtils {
|
||||||
|
private static final 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 的序列化问题
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将对象转换为 JSON 字符串
|
||||||
|
*
|
||||||
|
* @param obj 要转换的对象
|
||||||
|
* @return JSON 字符串
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static String toJsonString(Object obj) {
|
||||||
|
return OBJECT_MAPPER.writeValueAsString(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-framework</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>xiaoyi-spring-boot-starter-biz-operationlog</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>平台基础设施层:操作日志记录器</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>top.crushtj</groupId>
|
||||||
|
<artifactId>xiaoyi-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- AOP 切面 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package top.crushtj.framework.biz.operationlog;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import top.crushtj.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||||
|
import top.crushtj.framework.common.utils.JsonUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Aspect
|
||||||
|
public class ApiOperationLogAspect {
|
||||||
|
/** 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 */
|
||||||
|
@Pointcut("@annotation(top.crushtj.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
|
||||||
|
*/
|
||||||
|
private Function<Object, String> toJsonStr() {
|
||||||
|
return JsonUtils::toJsonString;
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package top.crushtj.framework.biz.operationlog.aspect;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @Title: ApiOperationLog
|
||||||
|
* @Description: 自定义注解,用于标记需要记录操作日志的方法
|
||||||
|
* @Author: ayi
|
||||||
|
* @Date: 2025/11/21
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Documented
|
||||||
|
public @interface ApiOperationLog {
|
||||||
|
/**
|
||||||
|
* API 功能描述
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String description() default "";
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package top.crushtj.framework.biz.operationlog.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import top.crushtj.framework.biz.operationlog.ApiOperationLogAspect;
|
||||||
|
|
||||||
|
@AutoConfiguration
|
||||||
|
public class ApiOperationLogAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ApiOperationLogAspect apiOperationLogAspect() {
|
||||||
|
return new ApiOperationLogAspect();
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
top.crushtj.framework.biz.operationlog.config.ApiOperationLogAutoConfiguration
|
||||||
Reference in New Issue
Block a user