【问题标题】:How to update header parameter and sent the same to Controller using AOP in Spring/Spring boot如何在 Spring/Spring boot 中使用 AOP 更新标头参数并将其发送到 Controller
【发布时间】:2019-01-20 00:54:19
【问题描述】:

如何在 Spring/Spring boot 中使用 AOP 更新 header 参数并将其发送到 Controller?我可以添加但无法将其发送到控制器。我在控制器中得到空值。我不想使用@Around。

  @Before("PointcutDefinition.controllerLayer()")
  public Object beforeAdvice(JoinPoint joinPoint)
  {
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    request.setAttribute("traceId", ServiceUtil.getTraceId());
    return request;
  }

更新:

我能够使用以下代码更新 traceId。

  @Around("execution(* com.test.api.*.*(..)) && " + "args(traceId,..)")
  public Object setTraceId(ProceedingJoinPoint joinPoint, String traceId) throws Throwable
  {
    String newTraceId = ServiceUtil.getTraceId();
    Object result = joinPoint.proceed(new Object[]
    { newTraceId, "", "", "", "", "", "", "", "", "" });
    return result;
  }

在我的控制器中,我有多个方法,参数数量不同。但是所有方法中的第一个参数是traceId。我想单独更新 traceId 并保持其他参数不变。但在上述方法中,我不得不传递所有论点。有没有办法我可以单独更新第一个参数并发送其余参数不变。

【问题讨论】:

  • 你要设置的是标题还是属性?
  • 我的控制器类 -> public ResponseEntity loginSession(@RequestHeader(value = "traceId", required = false) String traceId,...) 我想为 traceId 设置值。
  • 你为什么不想使用@Around?
  • 我很好使用@Around(如果这是实现这一目标的唯一方法)。我的印象是,只有当我们想在调用该方法之前和之后做某事时,我们才应该使用 Around。但就我而言,我想在调用方法之前而不是在调用方法之后做一些事情。

标签: spring spring-boot spring-mvc aop spring-aop


【解决方案1】:

我可以使用@Around 做到这一点。我相信使用@Before 是无法实现的。

  @Around("execution(* com.test.api.*.*(..)) && " + "args(traceId,..)")
  public Object setTraceId(ProceedingJoinPoint joinPoint, String traceId) throws Throwable
  {
    String newTraceId = ServiceUtil.getTraceId();
    Object[] obj = joinPoint.getArgs();
    obj[0] = newTraceId;
    return joinPoint.proceed(obj);
  }

【讨论】:

  • 在您的第一次尝试中,我看不到在请求上设置属性将如何导致获得额外的标头值。请求属性不是标头。
  • 你是对的@Robert Moskal。它没有打动我。
【解决方案2】:

您的问题不在于@Before 注释,而在于错误地在 HttpServletRequest 上设置了属性而不是标头。属性!=标题。因此,当然,该参数在您的控制器中将为空。

HttpServletRequest 上的标头是只读的。您需要将请求包装在 HttpServletRequestWrapper 中并执行各种工作以管理原始标头和您的自定义标头。例子很多,这里有一个完整的例子:https://wilddiary.com/adding-custom-headers-java-httpservletrequest/

它引入了一个扩展 HttpServletRequestWrapper 的 MutableHttpServletRequest。您将保留自定义标题的状态,并将它们与原始标题保持一致。您必须覆盖 getHeader 和 getHeaderNames!

您的@Before 代码如下所示:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
MutableHttpServletRequest wrappedRequest = new MutableHttpServletRequest(request);
request.putHeader("traceId", ServiceUtil.getTraceId());
return request;

但是,要获得一点点功能,这似乎还有很长的路要走(除非您需要一次又一次地这样做)。一次性我只使用@Around 技术。

所有这些仪式都为地图添加价值!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 2023-03-27
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 2019-07-25
    相关资源
    最近更新 更多