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