简体   繁体   English

如何使用spring boot和aspect记录请求正文

[英]How to log request body using spring boot and aspect

I have created an aspect to log the request body passed in a controller function:我创建了一个方面来记录在控制器函数中传递的请求主体:

This is what i am trying这就是我正在尝试的

@Pointcut("execution(* com.test.test.test.controller.*.* (..))")
  public void executeController() {}

  @Pointcut("execution(* com.test.test.common.exception.*.* (..))")
  public void executeExceptionAdvice() {}

  @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) || "
      + "@annotation(org.springframework.web.bind.annotation.PostMapping) || "
      + "@annotation(org.springframework.web.bind.annotation.PutMapping) ||"
      + "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)")
  public void logRequestMapping() {}

  @Before("logRequestMapping() && executeController() && args(..,@RequestBody requestBody) ")
  public void logRequestBody(JoinPoint joinPoint, Object requestBody) {
    LOGGER = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
    LOGGER.info("Method : {},Request Body:{}",
        LOGGER.getName() + "." + joinPoint.getSignature().getName(),
        MaskingUtil.jsonifyAndMask(requestBody));
  }

Now instead of matching with @RequestBody spring is matching arguments with .. ie generalize arguments and logging everything which is passed instead of the request body.I want to log only request body and if it is null the it won't print anything.现在,不是与@RequestBody 匹配,spring 是将参数与..匹配,即概括参数并记录传递的所有内容而不是请求正文。我只想记录请求正文,如果它为空,则不会打印任何内容。

You already found my related answer, but I just noticed the link in the comment under the wrong answer here after preparing an example for you.您已经找到了我的相关答案,但在为您准备了示例后,我才注意到此处错误答案下的评论中的链接。 BTW, I used pure POJO + AspectJ, not Spring AOP (only Spring libs on the classpath so as to be able to resolve the annotations), but the aspect should be the same there.顺便说一句,我使用了纯 POJO + AspectJ,而不是 Spring AOP(类路径上只有 Spring 库,以便能够解析注释),但方面应该是相同的。

PS: My example is better suited to your problem because the pointcut here specifically matches target methods bearing the @RequestBody annotation. PS:我的示例更适合您的问题,因为这里的切入点专门匹配带有@RequestBody注释的目标方法。 In the other example you would have to match all methods and then filter during runtime.在另一个示例中,您必须匹配所有方法,然后在运行时进行过滤。

Dummy target classes:虚拟目标类:

I use two classes to test both of your package names.我使用两个类来测试您的两个包名称。 Otherwise they are the same.否则它们是相同的。

package com.test.test.test.controller;

import org.springframework.web.bind.annotation.*;

public class MyController {
  // These should trigger the aspect
  @RequestMapping public String one(int number, @RequestBody String name) { return "Hey!"; }
  @PostMapping public void two(int number, @RequestBody String name) {}
  @PutMapping public String three(@RequestBody String name) { return "Ho!"; }
  @ExceptionHandler public void four(@RequestBody String name) {}

  // These should *not* trigger the aspect
  public String noAnnotation(@RequestBody String name) { return "No annotation"; }
  public String alsoNoAnnotation(String name) { return "Also no annotation"; }
  @RequestMapping public String five(int number, String name) { return "foo"; }
  @PostMapping public void six(int number, String name) {}
  @PutMapping public String seven(String name) { return "bar"; }
  @ExceptionHandler public void eight(String name) {}
}
package com.test.test.common.exception;

import org.springframework.web.bind.annotation.*;

public class MyExceptionHandler {
  // These should trigger the aspect
  @RequestMapping public String one(int number, @RequestBody String name) { return "Hey!"; }
  @PostMapping public void two(int number, @RequestBody String name) {}
  @PutMapping public String three(@RequestBody String name) { return "Ho!"; }
  @ExceptionHandler public void four(@RequestBody String name) {}

  // These should *not* trigger the aspect
  public String noAnnotation(@RequestBody String name) { return "No annotation"; }
  public String alsoNoAnnotation(String name) { return "Also no annotation"; }
  @RequestMapping public String five(int number, String name) { return "foo"; }
  @PostMapping public void six(int number, String name) {}
  @PutMapping public String seven(String name) { return "bar"; }
  @ExceptionHandler public void eight(String name) {}
}

Driver application:驱动程序应用:

package de.scrum_master.app;

import com.test.test.common.exception.MyExceptionHandler;
import com.test.test.test.controller.MyController;

public class Application {
  public static void main(String[] args) {
    MyController controller = new MyController();
    // These should trigger the aspect
    controller.one(1, "one");
    controller.two(2, "two");
    controller.three("three");
    controller.four("four");
    // These should *not* trigger the aspect
    controller.noAnnotation("none");
    controller.five(1, "five");
    controller.six(2, "six");
    controller.seven("seven");
    controller.eight("eight");
    controller.alsoNoAnnotation("none either");

    MyExceptionHandler handler = new MyExceptionHandler();
    // These should trigger the aspect
    handler.one(1, "one");
    handler.two(2, "two");
    handler.three("three");
    handler.four("four");
    // These should *not* trigger the aspect
    handler.noAnnotation("none");
    handler.five(1, "five");
    handler.six(2, "six");
    handler.seven("seven");
    handler.eight("eight");
    handler.alsoNoAnnotation("none either");
  }
}

Aspect:方面:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.bind.annotation.RequestBody;

@Aspect
public class MyAspect {
  @Pointcut("execution(* com.test.test.test.controller..*(.., @org.springframework.web.bind.annotation.RequestBody (*), ..))")
  public void executeController() {}

  @Pointcut("execution(* com.test.test.common.exception..*(.., @org.springframework.web.bind.annotation.RequestBody (*), ..))")
  public void executeExceptionAdvice() {}

  @Pointcut(
      "@annotation(org.springframework.web.bind.annotation.RequestMapping) || " +
      "@annotation(org.springframework.web.bind.annotation.PostMapping) || " +
      "@annotation(org.springframework.web.bind.annotation.PutMapping) ||" +
      "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)"
    )
  public void logRequestMapping() {}

  @Before(
    "logRequestMapping() &&" +
    "(executeController() || executeExceptionAdvice())"
  )
  public void logRequestBody(JoinPoint thisJoinPoint) {
    MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
    Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
    int index = -1;
    for (Annotation[] annotations : annotationMatrix) {
      index++;
      for (Annotation annotation : annotations) {
        if (!(annotation instanceof RequestBody))
          continue;
        Object requestBody = thisJoinPoint.getArgs()[index];
        System.out.println(thisJoinPoint);
        System.out.println("  Request body = " + requestBody);
      }
    }
  }
}

Console log:控制台日志:

execution(String com.test.test.test.controller.MyController.one(int, String))
  Request body = one
execution(void com.test.test.test.controller.MyController.two(int, String))
  Request body = two
execution(String com.test.test.test.controller.MyController.three(String))
  Request body = three
execution(void com.test.test.test.controller.MyController.four(String))
  Request body = four
execution(String com.test.test.common.exception.MyExceptionHandler.one(int, String))
  Request body = one
execution(void com.test.test.common.exception.MyExceptionHandler.two(int, String))
  Request body = two
execution(String com.test.test.common.exception.MyExceptionHandler.three(String))
  Request body = three
execution(void com.test.test.common.exception.MyExceptionHandler.four(String))
  Request body = four

也许你应该写下 @RequestBody 的完整路径:

@annotation(org.springframework...RequestBody) requestBody

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Spring 引导请求包装器主体 - Request Wrapper Body using Spring Boot 如何在 spring Webflux Java 中记录请求正文 - How to log request body in spring Webflux Java 如何使用 spring 引导登录/注销? - How to log in/ log out using spring boot? 在使用@Requestbody注释在Spring Boot中进行处理之前,如何在数据库或日志文件中记录JSON或XML请求 - How to log JSON or XML request in a database or log file before processing in Spring boot using @Requestbody annotation Spring 使用@RequestBody 时启动获取请求正文 - Spring Boot get the request body while using @RequestBody 使用 Jackson 注释的 Spring Boot 多态请求体 - Spring boot polymorphic request body using Jackson annotations 如何在 Spring Boot 中使用 OpenAPI 3 从“响应”和“请求正文”中隐藏“模式”? - How to hide "Schema" from "response" and "Request body" using OpenAPI 3 in Spring Boot? 如何使用 Spring 引导框架在发布请求正文节点中接受 PascalCase 而不是 camelCase - How to accept PascalCase instead of camelCase in post request body nodes using Spring Boot Framework 在Spring Boot中记录请求有效负载 - Log request payload in Spring Boot 如何在 spring-boot 中启用 utf-8 请求体? - How to enable utf-8 request body in spring-boot?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM