在工做中,常常會遇到不一樣公司系統之間的遠程服務調用。遠程調用技術很是多,如rmi、netty、mina、hessian、dubbo、Motan、springcloud、webservice等等。雖然在互聯網的今天,可能大多數公司使用的都是些高大上的分佈式rpc調用技術,在多數程序員眼裏都以爲webservice技術很是的low,但博主不得不說它是公司與公司之間進行系統對接的最佳推薦技術。java
推薦緣由:程序員
1.webservice技術是創建在http+xml基礎之上的,很是的輕量級。web
2.webservice技術可經過wsdl來定義調用關係,雙方系統可根據wsdl快速的進行開發對接。spring
3.webservice是一種標準,有各類語言對它的實現,支持異構系統之間的對接。apache
4.必要狀況下,還可使用httpclient做爲客戶端進行調用,以下降依賴。服務器
1、webservice原理:app
客戶端——> 閱讀WSDL文檔 (根據文檔生成SOAP請求) ——>經過http調用發送到Web服務器——>交給WebService請求處理器 (ISAPI Extension)——>處理SOAP請求——> 調用WebService接口——>生成SOAP應答 ——> Web服務器經過http的方式返回客戶端dom
2、webservice通用調用技術httpclient(JAVA版)socket
工具類:分佈式
package com.empire.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sun.xml.internal.messaging.saaj.util.Base64; /** * 類HttpClientCallSoapUtils.java的實現描述:http調用webservice工具類 * * @author arron 2018年x月xx日 下午x0:0x:33 */ public class HttpClientCallSoapUtils { private static final Logger logger = LoggerFactory.getLogger(HttpClientCallSoapUtils.class); /** * 請求超時時間30秒 */ private static final int socketTimeout = 30000; /** * 傳輸超時時間30秒 */ private static final int connectTimeout = 30000; /** * 使用SOAP1.1發送消息 * * @param url 爲訪問的wsdl地址(登錄後wsdl文件中的soap:address) * @param soapXml * @param soapAction * @param userpass 認證用戶密碼格式:username:password(如:admin:123456) * @return */ public static String doPostSoap1_1(String url, String soapXml, String soapAction, String userpass) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); HttpPost httpPost = new HttpPost(url); //設置請求和傳輸超時時間 RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout) .setConnectTimeout(connectTimeout).build(); httpPost.setConfig(requestConfig); String result = null; CloseableHttpResponse response = null; try { httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8"); httpPost.setHeader("SOAPAction", soapAction); //httpPost.setHeader("Authorization", "Basic UzAwMTkyNTM4MDU6UDhaPFNdM0c="); if (StringUtils.isNotBlank(userpass)) { httpPost.addHeader(new BasicHeader("Authorization", "Basic " + new String(Base64.encode(userpass.getBytes())))); logger.info("加密後內容:{}", new BasicHeader("Authorization", "Basic " + new String(Base64.encode(userpass.getBytes())))); } StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8")); httpPost.setEntity(data); response = closeableHttpClient.execute(httpPost); HttpEntity httpEntity = response.getEntity(); if (httpEntity != null) { result = EntityUtils.toString(httpEntity, "UTF-8"); // 打印響應內容 logger.info("response:{}", result); } } catch (Exception e) { logger.error("exception in doPostSoap1_1", e); } finally { if (response != null) { try { EntityUtils.consume(response.getEntity()); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * 使用SOAP1.2發送消息 * * @param url 爲訪問的wsdl地址(登錄後wsdl文件中的soap:address) * @param soapXml * @param soapAction * @param userpass 認證用戶密碼格式:username:password(如:admin:123456) * @return */ public static String doPostSoap1_2(String url, String soapXml, String soapAction, String userpass) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); HttpPost httpPost = new HttpPost(url); // 設置請求和傳輸超時時間 RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout) .setConnectTimeout(connectTimeout).build(); httpPost.setConfig(requestConfig); String result = null; CloseableHttpResponse response = null; try { httpPost.setHeader("Content-Type", "application/soap+xml;charset=UTF-8"); httpPost.setHeader("SOAPAction", soapAction); //httpPost.setHeader("Authorization", "Basic UzAwMTkyNTM4MDU6UDhaPFNdM0c="); if (StringUtils.isNotBlank(userpass)) { httpPost.addHeader(new BasicHeader("Authorization", "Basic " + new String(Base64.encode(userpass.getBytes())))); logger.info("加密後內容:{}", new BasicHeader("Authorization", "Basic " + new String(Base64.encode(userpass.getBytes())))); } StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8")); httpPost.setEntity(data); response = closeableHttpClient.execute(httpPost); HttpEntity httpEntity = response.getEntity(); if (httpEntity != null) { // 打印響應內容 result = EntityUtils.toString(httpEntity, "UTF-8"); logger.info("response:{}", result); } } catch (Exception e) { logger.error("exception in doPostSoap1_2", e); } finally { if (response != null) { try { EntityUtils.consume(response.getEntity()); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * 把soap字符串格式化爲SOAPMessage * * @param soapString * @return */ public static SOAPMessage formartSoapString(String soapString) { MessageFactory msgFactory; try { msgFactory = MessageFactory.newInstance(); SOAPMessage reqMsg = msgFactory.createMessage(new MimeHeaders(), new ByteArrayInputStream(soapString.getBytes(Charset.forName("UTF-8")))); reqMsg.saveChanges(); return reqMsg; } catch (Exception e) { logger.error("formartSoapString()", e); return null; } } /** * @param envPrefix env的前綴,通常設置爲"soapenv" * @param isRemoveOldEnvPrefix 是否清楚默認前綴 * @param nameSpaceMap env中全部聲明的命名空間 * @param method 調用的webservice方法 * @param rootParm 傳輸的數據 * @param soapAction soupui上能夠看到xml上的soapAction * @return * @throws SOAPException */ public static SOAPMessage buildSoapMessage(String envPrefix, boolean isRemoveOldEnvPrefix, Map<String, String> nameSpaceMap, SoapElementNode method, SoapElementNode rootParm, String soapAction) throws SOAPException { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); message.getMimeHeaders().setHeader("SOAPAction", soapAction); // 建立soap消息主體========================================== SOAPPart soapPart = message.getSOAPPart();// 建立soap部分 SOAPEnvelope envelope = soapPart.getEnvelope(); envelope.setPrefix(envPrefix); //envelope.setPrefix("soapenv"); if (isRemoveOldEnvPrefix) { envelope.removeNamespaceDeclaration("SOAP-ENV"); } for (Entry<String, String> entry : nameSpaceMap.entrySet()) { envelope.addNamespaceDeclaration(entry.getKey(), entry.getValue()); } envelope.getHeader().setPrefix(envPrefix); if (isRemoveOldEnvPrefix) { envelope.getHeader().removeNamespaceDeclaration("SOAP-ENV"); } SOAPBody body = envelope.getBody(); //body.setPrefix("soapenv"); body.setPrefix(envPrefix); // 根據要傳給mule的參數,建立消息body內容。具體參數的配置能夠參照應用集成接口技術規範1.1/1.2版本 SOAPElement bodyElement = null; if (StringUtils.isNotBlank(method.getPrefix()) && StringUtils.isNotBlank(method.getNamespace())) { bodyElement = body.addChildElement(method.getLocalpart(), method.getPrefix(), method.getNamespace()); } if (StringUtils.isNotBlank(method.getPrefix()) && StringUtils.isBlank(method.getNamespace())) { bodyElement = body.addChildElement(method.getLocalpart(), method.getPrefix()); } if (StringUtils.isBlank(method.getPrefix()) && StringUtils.isBlank(method.getNamespace())) { bodyElement = body.addChildElement(method.getLocalpart()); } buidParamSOAP(bodyElement, rootParm); // Save the message message.saveChanges(); return message; } private static void buidParamSOAP(SOAPElement soapElement, SoapElementNode rootParm) throws SOAPException { if (StringUtils.isNotBlank(rootParm.getLocalpart())) { SOAPElement curr = null; if (StringUtils.isNotBlank(rootParm.getPrefix()) && StringUtils.isNotBlank(rootParm.getNamespace())) { curr = soapElement.addChildElement(rootParm.getLocalpart(), rootParm.getPrefix(), rootParm.getNamespace()); } if (StringUtils.isNotBlank(rootParm.getPrefix()) && StringUtils.isBlank(rootParm.getNamespace())) { curr = soapElement.addChildElement(rootParm.getLocalpart(), rootParm.getPrefix()); } if (StringUtils.isBlank(rootParm.getPrefix()) && StringUtils.isBlank(rootParm.getNamespace())) { curr = soapElement.addChildElement(rootParm.getLocalpart()); } if (StringUtils.isNotBlank(rootParm.getValue()) && curr != null) { curr.addTextNode(rootParm.getValue()); } soapElement = curr; } List<SoapElementNode> currChildNodeLists = rootParm.getChildNodeLists(); if (currChildNodeLists != null && currChildNodeLists.size() > 0) { for (int i = 0, j = currChildNodeLists.size(); i < j; i++) { buidParamSOAP(soapElement, currChildNodeLists.get(i)); } } } public static void main(String[] args) { String soapAction = ""; String postuirl = "http://localhost/empire_wccmass/empire/c4cws"; SoapElementNode root = new SoapElementNode(); root.setLocalpart("appointmentC4CInfo"); List<SoapElementNode> rootChildList = new ArrayList<SoapElementNode>(); rootChildList.add(new SoapElementNode("appointDate", "2018-01-13")); rootChildList.add(new SoapElementNode("appointTime", "1")); rootChildList.add(new SoapElementNode("c4cAptId", "20170801")); rootChildList.add(new SoapElementNode("dealerNo", "12178")); rootChildList.add(new SoapElementNode("getinType", "1")); rootChildList.add(new SoapElementNode("miles", "1234")); rootChildList.add(new SoapElementNode("status", "1")); rootChildList.add(new SoapElementNode("vinCode", "LVVDC11B9EC090288")); rootChildList.add(new SoapElementNode("wccMemberId", "10")); root.setChildNodeLists(rootChildList); Map<String, String> nameSpaceMap = new HashMap<>(); nameSpaceMap.put("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); nameSpaceMap.put("dao", "http://dao.interfaces.empire.com/"); SoapElementNode method = new SoapElementNode(); method.setLocalpart("syncAppointmentC4C"); method.setPrefix("dao"); try { SOAPMessage x = buildSoapMessage("soapenv", true, nameSpaceMap, method, root, ""); TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); // Get reply content Source source = x.getSOAPPart().getContent(); ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); StreamResult result = new StreamResult(bos); tf.transform(source, result); String rqXml = new String(bos.toByteArray()); logger.info("請求webservice的soap消息:{}", rqXml); //將構建的soap的xml打印出來 便於調試 System.out.println("請求webservice的soap消息:"+ rqXml); String respXml = doPostSoap1_2(postuirl, rqXml, soapAction, null); logger.info("webservice返回的soap消息:{}", respXml); System.out.println("webservice返回的soap消息:"+respXml); SOAPMessage a = formartSoapString(respXml); org.w3c.dom.Document ax = a.getSOAPBody().extractContentAsDocument(); String clubAptId = ax.getElementsByTagName("clubAptId").item(0).getTextContent(); String success = ax.getElementsByTagName("success").item(0).getTextContent(); logger.info("webservice返回的soap消息中是否成功:{},預定單Id:{}", success, clubAptId); System.out.println("webservice返回的soap消息中是否成功:"+success+",預定單Id:"+clubAptId); } catch (Exception e) { logger.error("", e); } } }
本身封裝的soap節點轉換類
package com.empire.util; import java.io.Serializable; import java.util.List; /** * * 類SoapElementNode.java的實現描述:soap節點轉換類 * @author arron 2018年x月xx日 下午x0:0x:33 */ public class SoapElementNode implements Serializable{ /** * 節點前綴 */ private String prefix=""; /** * 節點名 */ private String localpart=""; /** * 節點值 */ private String value=""; /** * 節點命名空間 */ private String namespace=""; private List<SoapElementNode> childNodeLists=null; public SoapElementNode(){} public SoapElementNode( String localpart) { super(); this.localpart = localpart; } public SoapElementNode( String localpart,String value) { super(); this.localpart = localpart; this.value=value; } public SoapElementNode(String prefix, String localpart,String value, String namespace) { super(); this.prefix = prefix; this.localpart = localpart; this.value=value; this.namespace = namespace; } public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getLocalpart() { return localpart; } public void setLocalpart(String localpart) { this.localpart = localpart; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace = namespace; } public List<SoapElementNode> getChildNodeLists() { return childNodeLists; } public void setChildNodeLists(List<SoapElementNode> childNodeLists) { this.childNodeLists = childNodeLists; } }
調用結果:
最後,博主今天的分享就到這裏,爲何博主要直接使用httpclient呢,由於客戶一個功能整一個wsdl,並且域名有三套,三套域名對應的系統代碼竟然不同,至關於作一個功能就要整三套,博主這天都被折磨瘦了幾斤,故不得已親自動手解決問題。
你們若是以爲文章不錯,請爲博主點一個贊,並持續關注博主按期乾貨分享。