竹简文档
切面处理

日志切面

通过 AOP 自动记录 Controller、Service、Repository 三层的请求日志与性能指标

LogAspectHandler

LogAspectHandler 是基于 Spring AOP 的日志切面处理器,通过 @Around 切点自动拦截方法调用,记录请求参数、返回值和执行耗时。

MVC vs WebFlux 对比

对比项MVC 版本WebFlux 版本
切点范围Controller + Service + Repository仅 Controller
响应式支持支持 Mono/Flux 返回类型
自动配置类BaseSdkAutoConfigurationWebFluxSdkAutoConfiguration

切点定义

字段

类型

切面结构

仅 MVC

LogAspectHandler.java
@Aspect
@Component
public class LogAspectHandler {

    // Controller 层 — 记录 HTTP 请求完整信息
    @Around("@within(org.springframework.stereotype.Controller) || " +
            "@within(org.springframework.web.bind.annotation.RestController)")
    public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录请求方法、路径、参数
        // 执行目标方法
        // 记录响应状态和耗时
    }

    // Service 层 — DEBUG 级别调用链路记录
    @Around("@within(org.springframework.stereotype.Service)")
    public Object aroundService(ProceedingJoinPoint joinPoint) throws Throwable {
        // 以 DEBUG 级别记录方法调用
        // 执行目标方法
    }

    // Repository 层 — DAO 执行耗时记录
    @Around("@within(org.springframework.stereotype.Repository)")
    public Object aroundRepository(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录 DAO 方法执行耗时
        // 支持 @IgnoreOutputDAO 跳过输出
    }
}

仅 WebFlux

WebFlux 版本能够正确处理 MonoFlux 响应式返回类型:

LogAspectHandler.java
// 响应式日志切面,由自动配置注册
@Aspect
public class LogAspectHandler {

    // 匹配所有 @RestController 标注类的所有方法
    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // ...
    }
}

响应式返回类型处理

LogAspectHandler.java
// 对于 Mono 返回类型,使用 doOnSuccess / doOnError 记录日志
if (result instanceof Mono<?> mono) {
    return mono
            .doOnSuccess(value -> logResponse(joinPoint, value))
            .doOnError(error -> logError(joinPoint, error));
}

// 对于 Flux 返回类型,使用 doOnComplete / doOnError 记录日志
if (result instanceof Flux<?> flux) {
    return flux
            .doOnComplete(() -> logComplete(joinPoint))
            .doOnError(error -> logError(joinPoint, error));
}

ServerWebExchange 提取

LogAspectHandler.java
// 遍历方法参数,查找 ServerWebExchange 实例
ServerWebExchange exchange = null;
for (Object arg : joinPoint.getArgs()) {
    if (arg instanceof ServerWebExchange) {
        exchange = (ServerWebExchange) arg;
        break;
    }
}

Controller 层日志

Controller 层切面记录完整的 HTTP 请求信息:

[INFO] [HTTP] >> GET /api/v1/user/1
[INFO] [HTTP] >> Headers: {Authorization: Bearer ***}
[INFO] [HTTP] >> Parameters: {id: 1}
[INFO] [HTTP] << 200 OK (15ms)

日志内容包括:

  • 请求方法(GET、POST 等)
  • 请求路径
  • 请求头(敏感信息自动脱敏)
  • 请求参数
  • 响应状态码
  • 处理耗时

Service 层日志(仅 MVC)

Service 层使用 DEBUG 级别记录,仅在开发和调试阶段可见:

[DEBUG] [SERVICE] UserService.getUserById(id=1)
[DEBUG] [SERVICE] UserService.getUserById -> UserVO{id=1, username='test'}

Repository 层日志(仅 MVC)

Repository 层记录 DAO 方法的执行耗时:

[INFO] [DAO] UserMapper.selectById(1) -> completed in 3ms

@IgnoreOutputDAO

对于返回大量数据的 DAO 方法,可使用 @IgnoreOutputDAO 注解跳过返回值日志输出:

UserMapper.java
public interface UserMapper extends BaseMapper<UserEntity> {

    // 该方法的返回值不会被日志切面输出
    @IgnoreOutputDAO
    List<UserEntity> selectAllUsers();

    // 普通方法仍会输出返回值
    UserEntity selectById(Long id);
}

日志输出内容(WebFlux)

字段说明
请求路径HTTP 请求的 URI
请求方法GET、POST、PUT、DELETE 等
客户端 IPServerWebExchange 中提取
方法签名Controller 类名与方法名
执行耗时方法执行时间(毫秒)
响应状态成功或异常

注意事项

  • Controller 层日志始终以 INFO 级别输出,确保生产环境可见
  • Service 层日志以 DEBUG 级别输出,生产环境默认不可见
  • Repository 层支持 @IgnoreOutputDAO 注解,避免大数据量返回值污染日志
  • 该切面由自动配置注册,无需手动声明 Bean

下一步

On this page