当前位置: 首页 > 知识库问答 >
问题:

如何使用Spring Boot和aspect记录请求主体

程亦
2023-03-14

我创建了一个方面来记录在控制器函数中传递的请求体:

这就是我正在尝试的

@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));
  }

现在,spring没有与@RequestBody匹配,而是将参数与。。i、 e.泛化参数并记录传递的所有内容,而不是请求体。我只想记录请求主体,如果为空,则不会打印任何内容。

共有2个答案

江迪
2023-03-14

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

@annotation(org.springframework...RequestBody) requestBody
南宫俊喆
2023-03-14

你已经找到了我的相关答案,但在为你准备了一个例子后,我刚刚注意到评论中错误答案下面的链接。顺便说一句,我使用的是纯POJO AspectJ,而不是Spring AOP(只有类路径上的Spring LIB才能解析注释),但在那里方面应该是相同的。

附言:我的例子更适合你的问题,因为这里的切入点特别匹配带有@Request estBody注释的目标方法。在另一个例子中,你必须匹配所有方法,然后在运行时过滤。

虚拟目标类:

我使用两个类来测试你的两个包名。否则它们是相同的。

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) {}
}

驱动程序应用程序:

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");
  }
}

方面:

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);
      }
    }
  }
}

控制台日志:

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
 类似资料:
  • 我在改型API中找不到记录完整请求/响应体的相关方法。我希望在探查器中得到一些帮助(但它只提供关于响应的元数据)。我尝试在构建器中设置日志级别,但这也没有帮助: 编辑:此代码正在工作。我不知道为什么它在早些时候不起作用。可能是因为我用的是旧版本的改装。

  • 最后是网关服务的application.yml文件...

  • 问题内容: 我想将所有传入和传出请求记录到一个特定的日志文件中。但是,我通过以下配置获得的只是控制台输出。怎么了 log4j2.xml: src / main / resources / META-INF / cxf / org.apache.cxf.Logger: 问题答案: 解决方法是,我现在使用和桥依赖。

  • 问题内容: 我需要所有已登录的SOAP请求,以及持续时间(处理请求所花费的时间)。 最好的方法是什么?看起来可以为Spring WebServices配置log4j,但是它将记录所有值吗? 将以下行添加到log4j.xml 编辑:我们实际上是在使用,而不是。另外,看起来可以通过配置PayloadLoggingInterceptor来做到这一点 但是我不确定日志消息会去哪里。我将该拦截器添加到了我们

  • 我正在尝试使用<code>网络客户端 谢谢 -斯里尼

  • 问题内容: 我试图在laravel 5.3中使用Ajax删除记录,我知道这是一个常见问题,并且已经有很多关于此主题的在线解决方案和教程。我尝试了其中一些,但大多数都给了我同样的错误。我试图以不同的角度来完成这项任务,但是我被卡住了,找不到我错了,这就是为什么我将此问题添加为指导原则。 我正在尝试使用以下脚本删除记录。 Controller.php Routes.php 视野中 App.js 当我单