如何在使用第三方 Web 服务时使用 PayloadLoggingInterceptor 和 SOAPLoggingInterceptor 拦截器

How to use PayloadLoggingInterceptor and SOAPLoggingInterceptor interceptors while consuming a third party web service

在我的应用程序中,我正在使用由我的客户提供的第三方网络服务。

我已经在 Spring 和 Hibernate 框架上开发了我的应用程序,并且在一个模块中我正在使用这个第三方网络服务 url。我使用

生成了网络服务存根

javab2-maven-plugin

maven 插件在我的 pom.xml 文件中声明如下:

          <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!-- Package to store the generated file -->
                    <packageName>com.equifax.unsolicited.wsdl.stub</packageName>
                    <!-- Treat the input as WSDL -->
                    <wsdl>true</wsdl>
                    <!-- Input is not XML schema -->
                    <xmlschema>false</xmlschema>
                    <!-- The WSDL file that you saved earlier -->
                    <schemaFiles>Duk_CIS_Send_CreditStatus.wsdl</schemaFiles>
                    <!-- The location of the WSDL file -->
                    <schemaDirectory>${project.basedir}/src/main/wsdl</schemaDirectory>
                    <!-- The output directory to store the generated Java files -->
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <!-- Don't clear output directory on each run -->
                    <clearOutputDir>false</clearOutputDir>
                </configuration>
            </plugin>

我正在使用自动生成的 JAXB java 类 来调用 Web 服务。我创建了一个调用 Web 服务的服务 bean :

@Service("unsolicitResponseService")
public class UnsolicitResponseServiceImpl  implements UnsolicitResponseService{

    private static final Logger LOGGER = Logger.getLogger(UnsolicitResponseServiceImpl.class);

    @Autowired
    private WebServiceTemplate webServiceTemplate;


    @Override
    public void sendUnsolicitResponse() {

        LOGGER.debug("Calling Duke Web Service to Send Unsolicit Response ... ");
        try{
            ObjectFactory objecFactory = new ObjectFactory();       

            CreditStatusMsgType creditStatusMessage = objecFactory.createCreditStatusMsgType(); 
            creditStatusMessage.setMessageHeader(createMessageHeader(objecFactory));

            //WRAP THE CLASS AS THE INSTANCE OF JAXBELEMENT OTHERWISE IT WILL THROW MISSING ROOTELEMENT ERROR
            JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement = objecFactory.createSendCreditStatus(creditStatusMessage);

            //CREATE STRING WRITER TO LOG THE REQUEST           
            Object response = this.webServiceTemplate.marshalSendAndReceive(creditStatusMessageJaxbElement);

            LOGGER.debug("Jumio Web Service Response Reponse :"+response);

            LOGGER.debug("Unsolicit Response sent to Duke Successfully.");
        }catch(Exception ex){
            LOGGER.error("Exception generated while calling Web Service  to send unsolicit Response : "+ex.getLocalizedMessage(),ex);
        }       

    }

下面是 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:sws="http://www.springframework.org/schema/web-services"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:oxm="http://www.springframework.org/schema/oxm" 
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/web-services 
        http://www.springframework.org/schema/web-services/web-services-2.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd  http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


    <!-- DEFINE SOAP VERSION USED BY A WSDL -->
    <bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"> 
        <property name="soapVersion"> 

            <!-- FOR TEXT/XML -->   
            <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/>          
        </property> 
    </bean>

    <!-- LOCATION OF THE GENERATED JAVA FILEs -->    
    <oxm:jaxb2-marshaller id="marshaller" contextPath="com.equifax.unsolicited.wsdl.stub"/>


    <!-- CONFIGURE THE SPRING WEB SERVICE -->
    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"> 
        <constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/> 
        <property name="unmarshaller" ref="marshaller"/> 
        <property name="defaultUri"   value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/> 
    </bean>


    <sws:interceptors>

        <bean id="jumioPeyLoadLoggingInterceptor" class="com.test.datasource.logging.interceptor.PayloadLoggingInterceptor">
        </bean>

        <bean id="jumioSOAPLoggingInterceptor" class="com.test.datasource.logging.interceptor.SOAPLoggingInterceptor">
        </bean>
    </sws:interceptors>

</beans>

而且我还添加了新的日志记录类别,以将记录器级别设置为 DEBUG 模式:

以上代码调用网络服务成功。但是拦截器没有被调用。所以我无法记录 XML 请求和响应。

在这里,我假设这些拦截器在使用服务时不会工作。如果我在这里错了,请告诉我。

我指的是来自 HERE 的 Spring Web 服务。本站在发布web-service时对拦截器进行了说明

请告诉我我们应该在使用网络服务时使用这个拦截器吗?或者我应该如何打印 JAXB-ELEMENT 的请求和响应?

我在这里添加我已经实施的解决方案。我们可以通过两种方式实施此解决方案。我已经使用 JAXBContext 和 Marshaller 实现了下面列表中的第二个。

1> 日志 Request/Response 通过拦截器。

我们在使用 Web 服务时不能使用 PayloadLoggingInterceptorSOAPLoggingInterceptor

我们在使用 Web 服务时需要使用 ClientInterceptorClientInterceptorPayloadValidatingInterceptor class 实现,用于拦截 request/response 并根据 [=45 验证它=] 模式。

为此,我们需要提供如下拦截器参考:

<bean id="MyPayloadValidatingInterceptor" class="com.equifax.ic.datasource.jumio.ws.logging.interceptor.JumioPayloadValidatingInterceptor">
        <property name="schema" value="file:WebContent/WEB-INF/schemas/account-balance-service.xsd" />
        <property name="validateRequest" value="false" />
        <property name="validateResponse" value="false" />
    </bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"> 
        <constructor-arg ref="soapMessageFactory"/> <property name="marshaller" ref="marshaller"/> 
        <property name="unmarshaller" ref="marshaller"/> 
        <property name="defaultUri"   value="https://partnerstg.duke-energy.com:4443/DukCISSendCreditStatus?wsdl"/>     
        <property name="interceptors">
            <list>              
                <ref bean="MyPayloadValidatingInterceptor"/>                
            </list>         
        </property>     

    </bean>

2> 使用 JAXBContext

记录 Request/Response

这是我在我的应用程序中实施的解决方案,因为我们不应该只使用 PayloadValidatingInterceptor 来记录 reqeust/response。

private void logJAXBRequest(JAXBElement<CreditStatusMsgType> creditStatusMessageJaxbElement){
        LOGGER.debug("Logging Web Service Request ...");

        StringWriter writer = null;
        StreamResult streamResult = null;
        StringBuffer buffer = null;
        try{
             writer = new StringWriter();
             streamResult = new StreamResult(writer);

             JAXBContext jaxbContext = JAXBContext.newInstance(CreditStatusMsgType.class);
             Marshaller marshaller = jaxbContext.createMarshaller();
             marshaller.marshal(creditStatusMessageJaxbElement, streamResult);

             buffer = writer.getBuffer();

             LOGGER.debug("JAXB Webservice Request : "+ buffer.toString());

             writer.close();

        }catch(Exception ex){
            LOGGER.error("Exception generated while creating XML Logs of JAXB Request :",ex);
        }
    }

大家好,同事们。 显示 XML 请求/响应的主要方式有两种:

  1. 首先,您必须将 log4j 依赖项添加到 pom.xml 文件中:

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  2. 然后您必须log4j.properties文件放入应用程序的类路径中。当我开发 SOAP 服务时,我经常使用 Spring WS Maven artefact。不幸的是,usual resources 文件夹不是从头开始创建的,您必须手动创建它。然后你把 log4j.properties 文件放在那里。 log4j 配置的内容取决于您要使用的方法(请参阅下面的项目)。得到的结构如下:

  3. 使用标准 Message Logging and Tracing 方法和 log4j.properties 文件。除了 log4j 配置文件内容外,不应配置、开发、编写任何内容。 log4j 配置的内容应该如下(按原样使用这些内容):

    log4j.rootCategory=DEBUG, stdout
    log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE
    log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG
    
    log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%p [%c{3}] %m%n
    
  4. 使用 PayloadLoggingInterceptor & log4j.properties 文件。应该应用一些配置更改,但这种方法对我来说更灵活。首先,您必须将 PayloadLoggingInterceptor 添加到 MessageDispatcherServlet 配置文件中:

        <?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:context="http://www.springframework.org/schema/context"      xmlns:sws="http://www.springframework.org/schema/web-services"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd        http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
        <context:component-scan base-package="com.ln.springws"/>
    
        <sws:annotation-driven/>
    
        <sws:interceptors>
            <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
        </sws:interceptors>
    
        <sws:dynamic-wsdl id="holiday" portTypeName="HumanResource"        locationUri="http://localhost:8080/holidayService/"        targetNamespace="http://spring-ws-holidays.com/hr/definitions">
            <sws:xsd location="/WEB-INF/hr.xsd"/>
        </sws:dynamic-wsdl>
        </beans>
    

    最后将以下内容放入log4j.properties文件:

    log4j.rootLogger=debug, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%-5p [%c] - <%m>%n
    
  5. 由于这两种方法,您将在控制台中看到类似的内容: