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