如何在使用Camel Rest时记录请求有效负载?

时间:2016-11-15 16:34:04

标签: java json rest logging apache-camel

我想在使用Camel Rest端点时记录原始的'原始'请求体(例如JSON)。这样做的正确方法是什么?

我的设置(RouteBuilder)如下所示:

restConfiguration().component("jetty")
  .host(this.host)
  .port(this.port)
  .contextPath(this.contextPath)
  .bindingMode(RestBindingMode.json);

rest("myService/").post()
  .produces("application/json; charset=UTF-8")
  .type(MyServiceRequest.class)
  .outType(MyServiceResponse.class)
  .to(SERVICE_CONTEXT_IN);

from(SERVICE_CONTEXT_IN).process(this.serviceProcessor);

我的问题是,使用这种方法存储请求作为Exchange属性的机制“太晚了”,任何处理器在路由中都太晚了,即绑定已经发生并消耗了请求。此外,CamelHttpServletRequest的InputStream已被读取且不包含任何数据。

使用日志EIP的第一个地方就在单个处理器之前:

from(SERVICE_CONTEXT_IN).log(LoggingLevel.INFO, "Request: ${in.body}")
  .process(this.serviceProcessor);

但此时${in.body}已经是MyServiceRequest的一个实例。上面添加的日志只会产生Request: x.y.z.MyServiceRequest@12345678。我想记录的是绑定到POJO之前的原始JSON。

似乎没有内置的方法可以在RestConfigurationDefinition和RestDefinition中启用“原始”请求的记录。

我可以摆脱自动JSON绑定并手动读取HTTP Post请求的InputStream,记录并在专用处理器中执行手动解组等,但我想保留内置绑定。

4 个答案:

答案 0 :(得分:2)

我同意使用Camel Rest端点无法记录原始请求(我假设您指的是在任何自动绑定之前有效负载通过线路)。

但考虑到Roman Vottner,您可以按如下方式更改restConfiguration()

restConfiguration().component("jetty")
  .host(this.host)
  .port(this.port)
  .componentProperty("handlers", "#yourLoggingHandler")
  .contextPath(this.contextPath)
  .bindingMode(RestBindingMode.json);

您的#yourLoggingHandler需要在注册表中注册并实施org.eclipse.jetty.server.Handler。请参阅Jetty文档http://www.eclipse.org/jetty/documentation/current/jetty-handlers.html#writing-custom-handlers编写自定义处理程序。

答案 1 :(得分:1)

最后,我通过不使用REST DSL绑定和高度复杂的处理器来记录有效负载来解决这个问题:

restConfiguration().component("jetty")
  .host(this.host)
  .port(this.port)
  .contextPath(this.contextPath);

rest("myService/").post()
  .produces("application/json; charset=UTF-8")
  .to(SERVICE_CONTEXT_IN);

from(SERVICE_CONTEXT_IN).process(this.requestLogProcessor)
  .unmarshal()
  .json(JsonLibrary.Jackson, MyServiceRequest.class)
  .process(this.serviceProcessor)
  .marshal()
  .json(JsonLibrary.Jackson);

所有requestLogProcessor所做的就是将in正文作为InputStream读取,获取并记录字符串,并最终传递它。

答案 2 :(得分:0)

您可以通过以下方式解决此问题:

  1. 在您的特定路由上关闭RestBindingMode并按原样记录传入的请求字符串。
  2. 之后,您可以使用ObjectMapper将JSON字符串转换为IN类型对象。
  3. 在路由结束时,将java对象转换为JSON并将其放入exchange out主体,因为我们关闭了RestBindingMode。

    rest("myService/").post()
       .bindingMode(RestBindingMode.off)
       .to(SERVICE_CONTEXT_IN);
    

答案 3 :(得分:0)

在我的情况下,streamCaching之所以成功,是因为Stream仅可读一次。因此,我可以登录,但无法再转发尸体。我希望这可能对某人有帮助