spring boot 整合CXF

1.依賴jar包

<dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.4</version>
</dependency>

2.提供接口

@WebService(
    targetNamespace = "http://service.domain.dec.customs.workstack.zorasoft.com/", //命名空間,一般是接口的包名倒序
    name = "DecImport"//暴露服務名稱
)
@SOAPBinding(style = SOAPBinding.Style.RPC) // 修改soap綁定樣式,生成wsdl會不一樣
@MTOM //開啓mtom模式
public interface DecImport {
    @WebMethod(action = "importDecInfo")
    WebServiceResponseData importDecInfo(@WebParam(name = "decInfo")DecInfo decInfo);
}

3.接口實現類

@WebService(
    serviceName = "DecImportService", // 與接口中指定的name一致
    portName = "DecImportPort",
    targetNamespace = "http://service.domain.dec.customs.workstack.zorasoft.com/",  // 必須與接口一樣
    endpointInterface = "com.zorasoft.workstack.customs.dec.domain.service.DecImport")// 接口地址
@Component
public class DecImportImpl implements DecImport {
    @Override
    public WebServiceResponseData importDecInfo(DecInfo decInfo) {

    }
}

4.發佈服務,默認服務在Host:port/services/***路徑下 其中services也可通過配置文件更改 如:cxf.path=/service

@Configuration
public class WebServiceConfig {
    @Autowired
    private Bus bus;

    @Autowired
    private DecImport decImport;

    @Bean
    public Endpoint decEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, decImport);
        endpoint.publish("/DecImport");//服務地址中的一部分http://localhost:8080/service/
DecImport?wsdl
        return endpoint;
    }

}

這裏相當於把DecImport接口發佈在了路徑/service/DecImport

最後發佈的服務爲:http://localhost:8080/service/DecImport?wsdl

5.客戶端調用(非使用wsdl文檔生成java類)有兩種方式

/**
* 方式1.代理類工廠的方式,需要拿到對方的接口
*/
public static void cl1() {
    try {
        // 接口地址
        String address = "http://localhost:8080/service/DecImport?wsdl";
        // 代理工廠
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
        // 設置代理地址
        jaxWsProxyFactoryBean.setAddress(address);
        // 設置接口類型
        jaxWsProxyFactoryBean.setServiceClass(CommonService.class);
        // 創建一個代理接口實現
        CommonService cs = (CommonService) jaxWsProxyFactoryBean.create();
        // 數據準備
       DecInfo decInfo = new DecInfo ();
        // 調用代理接口的方法調用並返回結果
        WebServiceResponseData result = cs.importDecInfo(decInfo)
        System.out.println("返回結果:" + result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
* 方式2.動態調用方式
*/
public static void cl2() {
    // 創建動態客戶端
    JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
    Client client = dcf.createClient("http://localhost:8080/service/DecImport?wsdl");
    // 需要密碼的情況需要加上用戶名和密碼
    // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME,
    // PASS_WORD));
    Object[] objects = new Object[0];
    try {
        // invoke("方法名",參數1,參數2,參數3....);

        DecInfo decInfo = new DecInfo ();
        objects = client.invoke("importDecInfo", decInfo );
        System.out.println("返回數據:" + objects[0]);
    } catch (java.lang.Exception e) {
        e.printStackTrace();
    }
}

 

=================================================================================

最後附上示例:

package com.zorasci.workstack.client.infrastructures.commons;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.service.model.*;

import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WebServiceUtil {

    private static Map<String, Endpoint> factoryMap = new HashMap<>();
    private static Map<String, Client> clientMap = new HashMap<>();

    /**
     *
     * @param wsdlUrl  wsdl的地址:http://localhost:8080/service/DecImport?wsdl
     * @param methodName 調用的方法名稱 importDecInfo
     * @param targetNamespace 命名空間  http://service.domain.dec.customs.workstack.zorasoft.com/
     * @param name  name 實現類名(可不填)
     * @param paramList 參數集合  
     * @throws Exception
     */
    public  static WebResponseContext dynamicCallWebServiceByCXF(String wsdlUrl, String methodName, String targetNamespace, String name, List<Object> paramList)throws Exception {
        ObjectMapper mapper  = new ObjectMapper();
        //臨時增加緩存,增加創建速度
        if (!factoryMap.containsKey(methodName)) {
            // 創建動態客戶端
            JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
            // 創建客戶端連接
            Client client = factory.createClient(wsdlUrl);
            Endpoint endpoint = client.getEndpoint();
            factoryMap.put(methodName, endpoint);
            clientMap.put(methodName, client);
        }
        //從緩存中換取 endpoint、client
        Endpoint endpoint = factoryMap.get(methodName);
        Client client = clientMap.get(methodName);
        // Make use of CXF service model to introspect the existing WSDL
        ServiceInfo serviceInfo = endpoint.getService().getServiceInfos().get(0);

        // 創建QName來指定NameSpace和要調用的service
        QName opName = new QName(targetNamespace,methodName);
        BindingInfo binding= endpoint.getEndpointInfo().getBinding();

        BindingOperationInfo boi = binding.getOperation(opName);
        BindingMessageInfo inputMessageInfo = boi.getInput();
//        BindingMessageInfo inputMessageInfo = null;
//        if (!boi.isUnwrapped()) {
//            //OrderProcess uses document literal wrapped style.
//            inputMessageInfo = boi.getWrappedOperation().getInput();
//        } else {
//            inputMessageInfo = boi.getUnwrappedOperation().getInput();
//        }

        List<MessagePartInfo> parts = inputMessageInfo.getMessageParts();

        /***********************以下是初始化參數,組裝參數;處理返回結果的過程******************************************/
        Object[] parameters = new Object[parts.size()];
        for (int m = 0; m < parts.size(); m++) {
            MessagePartInfo part = parts.get(m);
            // 取得對象實例
            Class<?> partClass = part.getTypeClass();
            //實例化對象
            Object initDomain = null;
            //普通參數的形參,不需要fastJson轉換直接賦值即可
            System.out.println("...........partClass.getCanonicalName()..........."+partClass.getCanonicalName());
            if ("java.lang.String".equalsIgnoreCase(partClass.getCanonicalName())
                    || "int".equalsIgnoreCase(partClass.getCanonicalName())) {
                initDomain = String.valueOf(paramList.get(m));
            }
            //如果是數組
            else if (partClass.getCanonicalName().indexOf("[]") > -1) {
                //轉換數組
                initDomain = mapper.readValue(mapper.writeValueAsString(paramList.get(m)), partClass.getComponentType());
            }else if(partClass.newInstance() instanceof java.util.List){
                initDomain = EntityToDtoUtils.parse(mapper.writeValueAsString(paramList.get(m)), partClass.getComponentType());
            } else{
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
                mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
                initDomain = mapper.readValue(mapper.writeValueAsString(paramList.get(m)), partClass);
            }
            parameters[m] = initDomain;

        }
        //定義返回結果集
        Object[] result = null;
        //普通參數情況 || 對象參數情況  1個參數 ||ArryList集合
        try {
            result = client.invoke(opName, parameters);
        } catch (Exception ex) {
            ex.printStackTrace();
            return  ResponseUtil.error("參數異常" + ex.getMessage());
        }
        return mapper.readValue(mapper.writeValueAsString(result[0]), WebResponseContext.class);
    }
}
 

 


 

 

發佈了68 篇原創文章 · 獲贊 18 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章