Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring引导应用程序中序列化API请求参数的问题_Java_Spring Boot_Aspectj_Spring Aop_Objectmapper - Fatal编程技术网

Java Spring引导应用程序中序列化API请求参数的问题

Java Spring引导应用程序中序列化API请求参数的问题,java,spring-boot,aspectj,spring-aop,objectmapper,Java,Spring Boot,Aspectj,Spring Aop,Objectmapper,我编写了一个方面来序列化Spring boot应用程序中API的请求参数,使用DB,如下所示: @Pointcut("within(com.tm.web.rest.*)") public void applicationResourcePointcut() { // Method is empty as this is just a Pointcut, the implementations are in the advices. } /**

我编写了一个方面来序列化Spring boot应用程序中API的请求参数,使用DB,如下所示:

  @Pointcut("within(com.tm.web.rest.*)")
  public void applicationResourcePointcut() {
    // Method is empty as this is just a Pointcut, the implementations are in the advices.
  }


  /**
   * Advice that logs when a method is returned.
   *
   * @param joinPoint join point for advice
   */
  @AfterReturning(value = ("applicationResourcePointcut()"),
      returning = "returnValue")


public void capturePayloadWhileReturning(JoinPoint joinPoint, Object returnValue)  {
    
    CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();

    Map<String, Object> argumentNameValueMap = new HashMap<>();

    if (codeSignature.getParameterNames() == null) {
      return mapper.writeValueAsString(argumentNameValueMap);
    }

    for (int i = 0; i < codeSignature.getParameterNames().length; i++) {
      String argumentName = codeSignature.getParameterNames()[i];
      Object argumentValue = joinPoint.getArgs()[i];
      argumentNameValueMap.put(argumentName, mapper.convertValue(argumentValue, Map.class));
    }
    String s = mapper.writeValueAsString(argumentNameValueMap); 
}
对于
HttpServletRequest
的请求类型,我得到了StackOverflow错误

事实上,我想避免这些类型的争论。但我无法找到正确处理这一问题的方法


有人能帮忙吗?

乔伊,如果你问问题,尽量提供完整的答案,不要让志愿者帮你猜。在本例中,您在序列化数据时遇到问题,但您既没有提到您使用的序列化技术或工具,也没有从您的代码中识别它,因为aspect advice使用对象
映射器
,而您没有显示它是如何声明的。我不明白为什么这么多开发人员选择简洁而不是清晰

在谷歌搜索了
mapper.writeValueAsString(..)
之后,我发现你可能使用了Jackson。我假设这是真的

  • 因此,解决问题的一种方法就是为有问题的类编写一个自定义序列化程序,请参阅。通过调整映射器配置,也可以避免某些序列化异常

  • 另一种方法是避免序列化(或“json ising”)这些对象,而是将一些伪值或
    toString()
    的结果写入数据库。这就是你要问的吗?那你就可以

  • 只需在方面或方面中保留一个静态排除类列表
  • 使用
    try
    /
    catch
    块构建动态列表,并将Jackson未能序列化的类添加到列表中,下次避免对同一类进行序列化,或者
  • 只要始终使用
    try
    /
    catch
    ,返回到
    toString()
  • 我认为#1整体上会更好,但因为你的问题更多的是关于AOP而不是关于Jackson(也根据你选择的标签),我将向你展示#2.3

    进一步查看示例代码,它看起来有点奇怪:

    • 例如,由于
      void
      方法中的
      返回mapper.writeValueAsString(..)
      语句,它永远不会这样编译
    • 您绑定
      returnValue
      ,但从不使用它
    • 您可以在三个不同的位置调用
      codeSignature.getParameterNames()
      ,其中一个在循环中,而不是将值缓存在局部变量中。这应该简化
    • 您可以将签名强制转换为
      MethodSignature
      ,而不是更一般的
      CodeSignature
      。然后您就可以访问该方法的返回类型。SpringAOP无论如何都不支持拦截构造函数,只有AspectJ支持。假设您使用SpringAOP,唯一可以拦截的就是方法
    • 我不明白为什么您对每个方法参数值调用
      mapper.convertValue(..)
      ,试图将其转换为
      Map
      。为什么不直接使用
      writeValueAsString(..)
    • 检查
      getParameterNames()
      中的
      null
      ,但它从不返回
      null
      ,而是一个空数组。所以这个检查是没有必要的
    • 还请注意,只有在使用调试信息编译类时,存储参数名的整个想法才有效。否则就不会有任何真正的参数名,只有代理项,如
      arg0
      arg1
      等。因此,在实现这样的解决方案之前,您最好确保代码的编译方式正确
    • 在已经包含JSON对象的映射上调用
      mapper.writeValueAsString(argumentNameValueMap)
      会导致像
      “foo”
      这样的字符串再次被括在双引号中,比如
      “\“foo\”
      ,这可能不是您想要的。确保每个对象只序列化一次
    这是我的:

    样本组件:

    package de.scrum_master.spring.q64782403;
    导入org.springframework.stereotype.Component;
    导入javax.servlet.http.HttpServletRequest;
    导入java.io.ByteArrayInputStream;
    @组成部分
    公共类MyComponent{
    公共无效剂量测定法(){
    System.out.println(“做某事”);
    }
    公共整数相加(整数a、整数b){
    系统输出打印项次(“添加”);
    返回a+b;
    }
    public void someRequest(HttpServletRequest请求,字符串参数){
    System.out.println(“处理请求”);
    }
    public void someByteStream(int索引,ByteArrayInputStream){
    System.out.println(“处理字节数组输入流”);
    }
    公共字符串连接(字符串a、字符串b){
    System.out.println(“连接”);
    返回a+“”+b;
    }
    }
    
    驱动程序应用程序:

    package de.scrum_master.spring.q64782403;
    导入org.springframework.boot.SpringApplication;
    导入org.springframework.boot.autoconfigure.springboot应用程序;
    导入org.springframework.context.ConfigurableApplicationContext;
    导入org.springframework.mock.web.MockHttpServletRequest;
    导入java.io.ByteArrayInputStream;
    @SpringBoot应用程序
    公共类应用程序{
    公共静态void main(字符串[]args){
    try(ConfigurableApplicationContext上下文=SpringApplication.run(Application.class,args)){
    多斯塔夫(上下文);
    }
    }
    私有静态void doStuff(ConfigurableApplicationContext上下文){
    MyComponent MyComponent=context.getBean(MyComponent.class);
    myComponent.doSomething();
    添加(4,5);
    myComponent.SomeByTestStream(11,新的ByteArrayInputStream(新字节[1024]);
    someRequest(新的MockHttpServletRequest(“GET”,“my/request”),“foo”);
    连接(“你好”,“世界”);
    }
    }
    
    请注意,对于这个虚拟应用程序,我只使用了
    MockHttpServletRequest
    ,因此如果您希望
    java.lang.IllegalArgumentException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"])