如何将 CXF 客户端正确集成到 Spring Boot 中

Mar*_*tör 5 java cxf spring-boot

我正在研究如何将带有 CXF 的 SOAP 客户端构建到 Spring Boot 应用程序中的各种方法。特别是我对配置请求/响应日志感兴趣。

前提条件:CXF Maven 插件用于从 WSDL 文件生成 Java 存根。

我研究了许多教程 [1][2][3],它们的做法都略有不同。问题是是否有一种“官方认可”的方式将 CXF 客户端与 Spring Boot 集成。CXF 文档似乎没有说。

选项 1:BindingProvider

我正在使用的现有代码(不是我的)就是这样做的:

@Bean
public PartnerServicePortType partnerServicePortType() {
  PartnerServicePortType partnerServicePortType = new PartnerServiceV0().getPartnerService();
  configureService((BindingProvider) partnerServicePortType, Services.PARTNER_SERVICE.serviceName());
  return partnerServicePortType;
}

private void configureService(BindingProvider bindingProvider, String path) {
  bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, baseUrl + path);
  if (!StringUtils.isEmpty(username)) {
    bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
  }

  /* add logging interceptors
  Client client = ClientProxy.getClient(bindingProvider);
  Endpoint cxfEndpoint = client.getEndpoint();

  cxfEndpoint.getInInterceptors().add(new PayloadExtractingLoggingInInterceptor());
  cxfEndpoint.getInFaultInterceptors().add(new PayloadExtractingLoggingInInterceptor());
  cxfEndpoint.getOutInterceptors().add(new PayloadExtractingLoggingOutInterceptor());
  cxfEndpoint.getOutFaultInterceptors().add(new PayloadExtractingLoggingOutInterceptor());
  */
}
Run Code Online (Sandbox Code Playgroud)

PartnerServiceV0是生成的扩展类,javax.xml.ws.Service如下所示:

@WebServiceClient(name = "PartnerService_v0", 
                  wsdlLocation = "classpath:some.wsdl",
                  targetNamespace = "urn:some-namespace") 
public class PartnerServiceV0 extends Service {
Run Code Online (Sandbox Code Playgroud)

如您所见,我添加了代码以启用对configureServcie方法的请求/响应日志记录。虽然这确实有效,但我们必须为每项服务完成所有这些工作,这感觉有些奇怪。

选项 2:JaxWsProxyFactoryBean

出于验证目的,我将上述代码移植到使用JaxWsProxyFactoryBeans

@Bean(name = "partnerService")
public PartnerServicePortType generateProxy() {

  JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
  proxyFactory.setServiceClass(PartnerServicePortType.class);
  proxyFactory.setAddress(baseUrl + Services.PARTNER_SERVICE.serviceName());
  if (!StringUtils.isEmpty(username)) {
    proxyFactory.setUsername(username);
    proxyFactory.setPassword(password);
  }
  return (PartnerServicePortType) proxyFactory.create();
}
Run Code Online (Sandbox Code Playgroud)

添加日志配置是我仍然需要使用此策略弄清楚的事情。

我查过的教程

  1. https://blog.codecentric.de/2016/07/spring-boot-apache-cxf-logging-monitoring-logback-elasticsearch-logstash-kibana/
  2. http://www.baeldung.com/apache-cxf-with-spring
  3. http://www.littlebigextra.com/consume-secure-soap-web-service-spring-boot-application/

ali*_*ani 1

我使用一些带有 cxf 的 jax-ws Web 服务,如下代码所示

package org.roshan.framework.config;

import java.io.IOException;
import java.net.MalformedURLException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import javax.inject.Inject;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.roshan.framework.config.PaymentProperties.WebServiceDetail.SSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import com.tosan.modern.epayment.webservice.merchant.paymentservice.TosanIPGWS;
import com.tosan.modern.yaghut.service.SoapServices;


@Configuration
public class WebServiceClient {

    @Inject
    private PaymentProperties paymentProperties;

    @Autowired
    private ResourceLoader resourceLoader;

    @Bean(name = "PaymentWebService")
    public TosanIPGWS PaymentWebServiceCLient() throws MalformedURLException {

        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(TosanIPGWS.class);
        factory.setAddress(paymentProperties.getShaparak().getWsPublicUrl());

        TosanIPGWS service = (TosanIPGWS) factory.create();
        try {
            final Client client = ClientProxy.getClient(service);
            // client.getInInterceptors().add(new LoggingInInterceptor());
            // client.getOutInterceptors().add(new LoggingOutInterceptor());
            setupSsl((HTTPConduit) client.getConduit(), paymentProperties.getShaparak().getSsl());
        } catch (Exception e) {
//          System.out.println("PaymentWebServiceCLient v9898989898");
            System.out.println(e.getMessage());
        }
        return service;
    }



    private void setupSsl(HTTPConduit httpConduit, SSL ssl) throws Exception {

        final String keyStoreLoc = ssl.getKeyStore();
        final String keyPassword = ssl.getKeyStorePassword();
        final String keystoreType = ssl.getKeyStoreType();
        final String trustStoreLoc = ssl.getTrustStore();
        final String trustStorePassword = ssl.getTrustStorePassword();
        final String trustStoreType = ssl.getTrustStoreType();

        final TLSClientParameters tlsCP = new TLSClientParameters();

        tlsCP.setDisableCNCheck(true);

        if (ssl.getKeyStore() != null && !ssl.getKeyStore().isEmpty()) {
            final KeyStore keyStore = KeyStore.getInstance(keystoreType);
            Resource resource1 = resourceLoader.getResource(keyStoreLoc);
            keyStore.load(resource1.getInputStream(), keyPassword.toCharArray());
            final KeyManager[] myKeyManagers = getKeyManagers(keyStore, keyPassword);
            tlsCP.setKeyManagers(myKeyManagers);
        }

        if (ssl.getTrustStore() != null && !ssl.getTrustStore().isEmpty()) {
            final KeyStore trustStore = KeyStore.getInstance(trustStoreType);
            Resource resource2 = resourceLoader.getResource(trustStoreLoc);
            trustStore.load(resource2.getInputStream(), trustStorePassword.toCharArray());
            final TrustManager[] myTrustStoreKeyManagers = getTrustManagers(trustStore);
            tlsCP.setTrustManagers(myTrustStoreKeyManagers);
        }

        httpConduit.setTlsClientParameters(tlsCP);
    }

    private static TrustManager[] getTrustManagers(KeyStore trustStore) throws NoSuchAlgorithmException, KeyStoreException {
        String alg = KeyManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory fac = TrustManagerFactory.getInstance(alg);
        fac.init(trustStore);
        return fac.getTrustManagers();
    }

    private static KeyManager[] getKeyManagers(KeyStore keyStore, String keyPassword) throws GeneralSecurityException, IOException {
        String alg = KeyManagerFactory.getDefaultAlgorithm();
        char[] keyPass = keyPassword != null ? keyPassword.toCharArray() : null;
        KeyManagerFactory fac = KeyManagerFactory.getInstance(alg);
        fac.init(keyStore, keyPass);
        return fac.getKeyManagers();
    }

}
Run Code Online (Sandbox Code Playgroud)