在工做中,常常会遇到不一样公司系统之间的远程服务调用。远程调用技术很是多,如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,并且域名有三套,三套域名对应的系统代码竟然不同,至关于作一个功能就要整三套,博主这天都被折磨瘦了几斤,故不得已亲自动手解决问题。
你们若是以为文章不错,请为博主点一个赞,并持续关注博主按期干货分享。