Протоколирование запроса / ответа с помощью Apache CXF в формате XML

можно ли зарегистрировать запрос / ответ как XML с помощью CXF, в идеале в отдельный файл, чтобы я мог контролировать, что делает приложение?

5 ответов


добавьте в конечные точки и клиенты следующее:

<jaxws:features>
    <bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>

это будет регистрировать все в журнале сервера.

Если вы хотите зарегистрировать их в другом месте, то посмотрите на исходный код встроенного CXF LoggingInInterceptor и LoggingOutInterceptor. Вы можете следовать шаблону, который они используют, чтобы захватить сообщения на своем пути в / ИЗ и делать с ними то, что вам нравится.

добавьте свои собственные перехватчики в цепочку с чем-то вроде этого:

<jaxws:inInterceptors>
    <ref bean="myLoggingInInterceptor" />
</jaxws:inInterceptors>

Итак, я попробовал немного с этим. Чтобы получить XML-запрос и ответы, зарегистрированные, и если вы используете Log4J, вам нужно установить уровень журнала CXF в log4j.xml файл, подобный этому (>= INFO):

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

и в CXF.в XML должны содержащего это:

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

оба файла должны находиться в пути к классам.

чтобы отобразить сообщение soap, добавьте это в свой код:

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

запрос soap xml может быть легко зарегистрирован Пользователем в перехватчике. Скажем, у нас есть перехватчик с именем "wslogginginininterceptor", поэтому в контекстном файле он будет выглядеть следующим образом :

<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<bean id="logOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<bean id="wsLoggingInInterceptor" class="org.jinouts.webservice.logging.WSLoggingInInterceptor"/>


   <cxf:bus>
        <cxf:inInterceptors>
            <ref bean="loggingInInterceptor"/>
            <ref bean="wsLoggingInInterceptor"/>
        </cxf:inInterceptors>
        <cxf:outInterceptors>
            <ref bean="logOutInterceptor"/>            
       </cxf:outInterceptors>
    </cxf:bus>

в классе мы можем получить запрос xml следующим образом:

public class WSLoggingInInterceptor extends AbstractSoapInterceptor
{

    public WSLoggingInInterceptor ()
    {
        super(Phase.RECEIVE);
    }

    @Override
    public void handleMessage ( SoapMessage message ) throws Fault
    {
        //get the remote address
        HttpServletRequest httpRequest = (HttpServletRequest) message.get ( AbstractHTTPDestination.HTTP_REQUEST );
        System.out.println ("Request From the address : " + httpRequest.getRemoteAddr ( ) );

        try
        {
            // now get the request xml
            InputStream is = message.getContent ( InputStream.class );
            CachedOutputStream os = new CachedOutputStream ( );
            IOUtils.copy ( is, os );
            os.flush ( );
            message.setContent (  InputStream.class, os.getInputStream ( ) );
            is.close ( );

            System.out.println ("The request is: " + IOUtils.toString ( os.getInputStream ( ) ));
            os.close ( );
        }

        catch ( Exception ex )
        {
            ex.printStackTrace ( );
        }

    }

}

смотрите, здесь я также регистрирую адрес, откуда поступает запрос. Вы также можете получить дополнительную информацию из объекта "HttpServletRequest". вы можете иметь больше из : http://cxf.apache.org/docs/interceptors.html

для регистрации ответа xml вы можете посмотреть на этой теме


Если вы используете Spring с его Java-конфигурацией, есть 2 простых способа активировать ведение журнала SOAP-сообщений с Apache CXF:

  1. непосредственно на SpringBus-это полезно, если вы хотите регистрировать сообщения всех ваших конечных точек CXF:

    @Bean(name=Bus.DEFAULT_BUS_ID) public SpringBus springBus() { SpringBus springBus = new SpringBus(); LoggingFeature logFeature = new LoggingFeature(); logFeature.setPrettyLogging(true); logFeature.initialize(springBus); springBus.getFeatures().add(logFeature); return springBus; }

  2. активируйте ведение журнала отдельно на каждой открытой конечной точке CXF

    @Bean public Endpoint endpoint() { EndpointImpl endpoint = new EndpointImpl(springBus(), weatherService()); endpoint.publish(SERVICE_NAME_URL_PATH); endpoint.setWsdlLocation("Weather1.0.wsdl"); LoggingFeature logFeature = new LoggingFeature(); logFeature.setPrettyLogging(true); logFeature.initialize(springBus()); endpoint.getFeatures().add(logFeature); return endpoint; }

напомнить LoggingFeature.setPrettyLogging (true); метод для просмотра довольно печатных SOAP-сообщений и LoggingFeature.инициализировать (springBus ()); - без последнего магия не происходит. Для более чистого кода Вы также можете отделить LoggingFeature как отдельный Боб и ввести его либо в SpringBus, либо в Endpoint-Bean.


гораздо проще добавить свой собственный регистратор в свойства конечной точки. В этом случае перехватчик журналов по умолчанию будет искать ваш регистратор в свойствах конечной точки, и если он найдет его, он будет использовать его, иначе он создаст default. Вот мой пример использования:

<jaxws:endpoint
        xmlns:client="http://service.info.client.diasoft.services.stream.integration.cib.sberbank.ru"
        address="/diasoft/clientInfoWS"
        serviceName="client:ClientWS"
        implementor="#clientServiceImpl">
    <jaxws:properties>
        <entry key="MessageLogger" value-ref="logger"/>
    </jaxws:properties>
    <jaxws:features>
        <bean class="org.apache.cxf.feature.LoggingFeature"/>
    </jaxws:features>
</jaxws:endpoint>


<bean id="logger" class="org.apache.cxf.common.logging.LogUtils" factory-method="getLogger">
    <constructor-arg value="ru.sberbank.cib.integration.stream.services.diasoft.client.info.service.ClientWSImpl"/>
</bean>