spring boot 整合CXF

郗唯
2023-12-01

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);
    }
}
 

 

 

 

 类似资料: