【问题标题】:How to log Apache CXF Soap Request and Soap Response using Log4j?如何使用 Log4j 记录 Apache CXF Soap 请求和 Soap 响应?
【发布时间】:2011-11-09 13:31:29
【问题描述】:

我正在使用 Apache CXF 框架。 在我的客户端程序中,我需要记录 CXF SOAP 请求和 SOAP 响应。 当我使用

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress(host);
factory.setServiceClass(MyService.class);
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());

我在控制台中收到了这些 SOAP 请求和 SOAP 响应:

Nov 9, 2011 6:48:01 PM org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback onClose
INFO: Outbound Message
---------------------------
ID: 2
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns4:MYResponse
--------------------------------------

但我的实际要求是,我需要将它们放在日志文件中,而不是将它们打印到服务器控制台。

当我如图所示直接使用log4j时

log4j(factory.getInInterceptors().add(new LoggingInInterceptor()));
log4j(factory.getOutInterceptors().add(new LoggingOutInterceptor()));

它只在日志文件中打印truetrue

谁能告诉我如何配置这个?

【问题讨论】:

标签: log4j cxf


【解决方案1】:

您需要在/META-INF/cxf/下创建一个名为org.apache.cxf.Logger的文件(即:org.apache.cxf文件,扩展名为Logger),内容如下:

org.apache.cxf.common.logging.Log4jLogger

参考:Using Log4j Instead of java.util.logging

如果你替换标准:

<cxf:bus>
  <cxf:features>
    <cxf:logging/>
  </cxf:features>
</cxf:bus>

更详细:

<bean id="abstractLoggingInterceptor" abstract="true">
    <property name="prettyLogging" value="true"/>
</bean>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" parent="abstractLoggingInterceptor"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" parent="abstractLoggingInterceptor"/>

<cxf:bus>
    <cxf:inInterceptors>
        <ref bean="loggingInInterceptor"/>
    </cxf:inInterceptors>
    <cxf:outInterceptors>
        <ref bean="loggingOutInterceptor"/>
    </cxf:outInterceptors>
    <cxf:outFaultInterceptors>
        <ref bean="loggingOutInterceptor"/>
    </cxf:outFaultInterceptors>
    <cxf:inFaultInterceptors>
        <ref bean="loggingInInterceptor"/>
    </cxf:inFaultInterceptors>
</cxf:bus>

Apache CXF 将漂亮地打印 XML 消息,并使用适当的缩进和换行符格式化它们。很有用。更多相关信息here

【讨论】:

  • 嗨托马斯,目前在 META-INF 文件夹下,我有一个名为 MANIFEST.MF 的文件。您的意思是在 META-INF 下添加一个 cxf 文件夹吗?请告诉我如何创建这个文件 org.apache.cxf.Logger??
  • 是的,在/META-INF 中创建/cxf 文件夹,并在其中放置一个名为org.apache.cxf 的文件,扩展名为Logger。另请参阅我的更新。
  • 文件必须命名为org.apache.cxf,扩展名为Logger。据我所知,您创建了一个文件\META-INF\cxf\org\apache\cxf\Logger.class 而不是\META-INF\cxf\org.apache.cxf.Logger。我从来没有说过你需要创建一个\org\apache\cxf 的目录结构。这是文件名(很尴尬,我必须承认)。
  • 好的,看看Using Log4j Instead of java.util.logging,这真的是在你的项目中创建一个单行文件的问题……
  • 确保 org.apache.cxf 记录器设置为 ALLDEBUG
【解决方案2】:

另一种简单的方法是像这样设置记录器 - 确保在加载 cxf Web 服务相关类之前执行此操作。您可以在一些静态块中使用它。

YourClientConstructor() {

  LogUtils.setLoggerClass(org.apache.cxf.common.logging.Log4jLogger.class);

  URL wsdlURL = YOurURL;//

  //create the service
  YourService = new YourService(wsdlURL, SERVICE_NAME);
  port = yourService.getServicePort(); 

  Client client = ClientProxy.getClient(port);
  client.getInInterceptors().add(new LoggingInInterceptor());
  client.getOutInterceptors().add(new LoggingOutInterceptor());
}

然后入站和出站消息将打印到 Log4j 文件而不是控制台。确保您的 log4j 配置正确

【讨论】:

  • 我建议也启用漂亮的日志记录:AbstractLoggingInterceptor.setPrettyLogging(true)
【解决方案3】:

在 Preethi Jain szenario 中实现漂亮日志记录的最简单方法:

LoggingInInterceptor loggingInInterceptor = new LoggingInInterceptor();
loggingInInterceptor.setPrettyLogging(true);
LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
loggingOutInterceptor.setPrettyLogging(true);
factory.getInInterceptors().add(loggingInInterceptor);
factory.getOutInterceptors().add(loggingOutInterceptor);

【讨论】:

  • LoggingInInterceptor 和 LoggingOutInterceptor 已弃用:“改用日志模块 rt/features/logging”
【解决方案4】:

在您的 spring 上下文中,下面的配置将记录请求和响应 soap 消息。

<bean id="loggingFeature" class="org.apache.cxf.feature.LoggingFeature">
    <property name="prettyLogging" value="true" />
</bean>

<cxf:bus>
    <cxf:features>
        <ref bean="loggingFeature" />
    </cxf:features>
</cxf:bus>

【讨论】:

    【解决方案5】:

    这对我有用。

    正常设置 log4j。然后使用此代码:

        // LOGGING 
        LoggingOutInterceptor loi = new LoggingOutInterceptor(); 
        loi.setPrettyLogging(true); 
        LoggingInInterceptor lii = new LoggingInInterceptor(); 
        lii.setPrettyLogging(true); 
    
        org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(isalesService); 
        org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 
    
        cxfEndpoint.getOutInterceptors().add(loi); 
        cxfEndpoint.getInInterceptors().add(lii);
    

    【讨论】:

    • @AI Grant,在哪里添加这个?
    【解决方案6】:

    在配置log4j.properties 时,将org.apache.cxf 日志级别设置为INFO 足以看到普通的SOAP 消息:

    log4j.logger.org.apache.cxf=INFO
    

    DEBUG 太冗长了。

    【讨论】:

    • 将 org.apache 设置为 TRACE 是我尝试的第一件事,并且没有记录 SOAP 消息。唯一加载的就是TRACE [http-8080-1] [org.apache.cxf.service.invoker.AbstractInvoker] Invoking method ... 之类的东西,但这为时已晚,因为当解析失败时,根本不会记录请求...
    【解决方案7】:

    试试这个代码:

    EndpointImpl impl = (EndpointImpl)Endpoint.publish(address, implementor);
        impl.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
        impl.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());
    

    logback.xml里面需要放webservice的接口名:

    <appender name="FILE" class="ch.qos.logback.classic.sift.SiftingAppender">
        <discriminator
            class="com.progressoft.ecc.integration.logging.ThreadNameDiscriminator">
            <key>threadName</key>
            <defaultValue>unknown</defaultValue>
        </discriminator>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <expression>logger.contains("InterfaceWebServiceSoap")</expression>
            </evaluator>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>NEUTRAL</OnMatch>
        </filter>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>
        <sift>
            <appender name="FILE-${threadName}"
                class="ch.qos.logback.core.rolling.RollingFileAppender">
                <File>${LOGGING_PATH}/${threadName}.log</File>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>${ARCHIVING_PATH}/%d{yyyy-MM-dd}.${threadName}%i.log.zip
                    </FileNamePattern>
                    <MaxHistory>30</MaxHistory>
                    <TimeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                        <MaxFileSize>50MB</MaxFileSize>
                    </TimeBasedFileNamingAndTriggeringPolicy>
                </rollingPolicy>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <Pattern>%date{dd-MM-yyyy HH:mm:ss.SSS} | %5level | %-60([%logger{53}:%line]): %msg %ex{full} %n</Pattern>
                </encoder>
            </appender>
        </sift>
    </appender>
    
    <root>
        <level value="ALL" />
        <appender-ref ref="FILE" />
    </root>
    

    【讨论】:

      【解决方案8】:

      cxf.xml

      <cxf:bus>
          <cxf:ininterceptors>
              <ref bean="loggingInInterceptor" />
          </cxf:ininterceptors>
          <cxf:outinterceptors>
              <ref bean="logOutInterceptor" />
          </cxf:outinterceptors>
      </cxf:bus>
      

      org.apache.cxf.Logger

      org.apache.cxf.common.logging.Log4jLogger
      

      请查看截图here

      【讨论】:

        【解决方案9】:

        如果有人想这样做,使用 Play Framework(并使用 LogBack http://logback.qos.ch/),那么您可以使用以下行配置 application-logger.xml:

         <logger name="org.apache.cxf" level="DEBUG"/>
        

        对我来说,它成功了;)

        【讨论】:

        • 这会将每个soap服务日志都放在DEBUG,如果你有3个并且你想只为其中1个启用日志,这不适用......
        • 你是对的。但可以肯定的是,您将按照问题要求记录 CXF SOAP 请求和 SOAP 响应。
        【解决方案10】:

        使用log4j logger 的 SOAP/REST 请求/响应的客户端/服务器日志记录的全局设置过程。 这样您就可以为整个应用程序设置日志记录,而无需更改代码、war、jar 文件等。

        1. 将文件cxf-rt-features-logging-X.Y.Z.jar 安装到您的CLASS_PATH

        2. 创建文件(路径例如:/opt/cxf/cxf-logging.xml):

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
          <cxf:bus>
           <cxf:features>
           <bean class="org.apache.cxf.ext.logging.LoggingFeature">
           <property name="prettyLogging" value="true"/>
           </bean>
           </cxf:features>
           </cxf:bus>
           </beans>
          
        3. org.apache.cxf (log4j 1.x) log4j.logger.org.apache.cxf=INFO,YOUR_APPENDER 设置日志记录

        4. 在 java 启动时设置这些属性

        java ... -Dcxf.config.file.url=file:///opt/cxf/cxf-logging.xml -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true -Dcom.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true ...

        不知道为什么,但是也要设置变量com.sun.xml.*

        【讨论】:

          【解决方案11】:

          旧配置选项不适用于使用 Apache CXF 3.1 或更高版本的用户。检查here。就我而言,我在 spring boot(版本 2.4.2)项目中使用了 apache cxf 3.4.2。

          要正确打印日志,您需要在 Bus 对象中添加功能(在我的情况下,它是 SpringBus),如下所示 -

          1. 创建LoggingFeature -
          LoggingFeature loggingFeature = new LoggingFeature();
          loggingFeature.setPrettyLogging(true);
          
          1. 创建/自动装配总线对象,然后将功能设置为总线
          bus.setFeatures(Arrays.asList(loggingFeature));
          

          如果您需要查看如何在 Spring Boot 项目中创建总线,请查看here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-02
            • 1970-01-01
            • 1970-01-01
            • 2011-11-02
            • 2015-03-11
            • 2012-09-20
            相关资源
            最近更新 更多