SpringBoot調用第三方WebService接口的兩種方法
WebService簡介
WebService接口的發(fā)布通常一般都是使用WSDL(web service descriptive language)文件的樣式來發(fā)布的,該文檔包含了請求的參數信息,返回的結果信息,我們需要根據WSDL文檔的信息來編寫相關的代碼進行調用WebService接口。接下來我將采用常見的兩種方式調用WebService接口。
場景描述
目前我需要使用java調用C#系統(tǒng)的一個WebService接口,傳遞參數為一個表號,返回的是一個Xml的數據類型,需要實現調用接口,獲取到xml之后并解析為Json格式數據,并返回給前端。Java調用WebService接口,需要根據提供接口方的XSD文檔編寫相關代碼,Xsd文檔可以直接通過提供的接口地址進行查看。
WebServiceTemplate調用WebService接口實現
1.導入相關的依賴包,如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency>
2.使用WebServiceTemplate實現調用WebService接口,需要編寫先關的解析類,根據提供的XSDL文檔編寫先關代碼,XSDL文檔信息如下:
POST /rootServiceFlow/EBoardService.asmx HTTP/1.1 Host: 10.200.0.74 Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://tempuri.org/AAFlow002x" <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <AAFlow002x xmlns="http://tempuri.org/"> <LotNo>string</LotNo> </AAFlow002x> </soap:Body> </soap:Envelope>
上面的信息是包含請求所需要傳遞的參數,字段為LotNo。接下來XSDL的文檔信息為返回的數據格式,如下:
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <AAFlow002xResponse xmlns="http://tempuri.org/"> <AAFlow002xResult>string</AAFlow002xResult> </AAFlow002xResponse> </soap:Body> </soap:Envelope>
需要根據以上信息編寫請求類AAFlow002x,響應接收解析類AAFlow002xResponse,和ObjectFactory類,這三個類可以使用Idea的終端通過命令的方式生成對應的java類,也可以通過自己編寫生成java類。通過命令的方式如下:
xjc -d /path/to/output http://example.com/sample.xsd
/path/to/output為生成類的目錄,http://example.com/sample.xsd為webServce的接口地址,生成的類如下:
AAFlow002x類編寫如下: import lombok.Data; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "LotNo" }) @XmlRootElement(name = "AAFlow002x", namespace = "http://tempuri.org/") @Data public class AAFlow002x { @XmlElement(name = "LotNo", namespace = "http://tempuri.org/", required = true) protected String LotNo; }
AAFlow002xResponse類編寫如下: import lombok.Data; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AAFlow002xResponse", namespace = "http://tempuri.org/", propOrder = { "AAFlow002xResult" }) @XmlRootElement(name = "AAFlow002xResponse") @Data public class AAFlow002xResponse { @XmlElement(name = "AAFlow002xResult", namespace = "http://tempuri.org/", required = true) private String AAFlow002xResult; }
ObjectFatoty類編寫如下: import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlElementDecl; import javax.xml.bind.annotation.XmlRegistry; import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { private final static QName _AAFlow002_QNAME = new QName("http://tempuri.org/", "AAFlow002x"); private final static QName _AAFlow002Response_QNAME = new QName("http://tempuri.org/", "AAFlow002xResponse"); public ObjectFactory() { } public AAFlow002x createAAFlow002x() { return new AAFlow002x(); } public AAFlow002xResponse createAAFlow002xResponse() { return new AAFlow002xResponse(); } @XmlElementDecl(namespace = "http://tempuri.org/", name = "AAFlow002x") public JAXBElement<AAFlow002x> createAAFlow002x(AAFlow002x value) { return new JAXBElement<AAFlow002x>(_AAFlow002_QNAME, AAFlow002x.class, null, value); } @XmlElementDecl(namespace = "http://tempuri.org/", name = "AAFlow002yResponse") public JAXBElement<AAFlow002xResponse> createAAFlow002yResponse(AAFlow002xResponse value) { return new JAXBElement<AAFlow002xResponse>(_AAFlow002Response_QNAME, AAFlow002xResponse.class, null, value); } }
編寫使用WebServiceTemplate進行調用
@Service @Slf4j public class TestWebService { private static final String ENDPOINT_URL = "這里填寫你調用的WebService接口地址"; private static final String SOAP_ACTION = "http://tempuri.org/AAFlow002x"; public String getDataTable(String LotNo) { // 創(chuàng)建WebServiceTemplate對象 WebServiceTemplate webServiceTemplate = new WebServiceTemplate(); Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); // 設置解析類,這里填寫包的路徑為AAFlow002xResponse類所在路徑 marshaller.setContextPath("org.test.parse"); webServiceTemplate.setMarshaller(marshaller); webServiceTemplate.setUnmarshaller(marshaller); // 封裝請求參數 AAFlow002x aaFlow002 = new ObjectFactory().createAAFlow002x(); aaFlow002.setLotNo("22113102"); // 創(chuàng)建SOAP請求回調對象,這里的SOAP_ACTION指定你調用的接口的哪個方法 SoapActionCallback soapActionCallback = new SoapActionCallback(SOAP_ACTION); // 調用WebService接口,發(fā)送請求并返回數據 JAXBElement<AAFlow002xResponse> aaFlow002xResponse = (JAXBElement<AAFlow002xResponse>) webServiceTemplate.marshalSendAndReceive(ENDPOINT_URL, aaFlow002, soapActionCallback); String result = aaFlow002xResponse.getValue().getAAFlow002xResult(); // 輸出響應結果 System.out.println(aaFlow002xResponse.getValue().getAAFlow002xResult()); return result; } }
編寫完成之后,Debug啟動項目。出現如下圖所示證明調用接口成功:
我們可以針對以上代碼進行優(yōu)化,寫一個WebServiceConfig類,專門對WebServiceTemplate進行配置,這里就不在贅述。采用WebServiceTemplate接口調用WebService接口,雖然可以采用命令的方式生成對應的Java代碼,但是其缺點是如果請求的參數和返回的參數數據結構很復雜,生成的java類代碼就很復雜。
HttpClientBuilder調用WebService接口實現
@Override public JSONObject getDataFromMESSystem(String deviceNumber) { // 根據上面的XSDL文檔封裝請求參數 String strParameter = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + " <soap:Body>\n" + " <AAFlow002y xmlns=\"http://tempuri.org/\">\n" + " <LotNo>" + deviceNumber + "</LotNo>\n" + " </AAFlow002y>\n" + " </soap:Body>\n" + " </soap:Envelope>"; // 獲取數據,返回的是一個xml格式數據 String xmlData = doPostSoap(UrlConstant.MES_SERVICE_URL, strParameter, UrlConstant.MES_SOAP_URI); JSONObject jsonObject = null; try { // 將請求結果轉換成json類型 if(StringUtils.isNotBlank(xmlData)){ jsonObject = xml2Json(xmlData); } } catch (Exception e) { e.printStackTrace(); } return jsonObject; } /** * 發(fā)送Soap請求,并返回數據 * @param url WebService接口地址 * @param soap 封裝的請求參數 * @param SOAPAction 對應的調用方法uri * @return 返回xml數據,用一個字符串接收 */ public static String doPostSoap(String url, String soap, String SOAPAction) { // 請求體 String retStr = ""; // 創(chuàng)建HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); // HttpClient CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); HttpPost httpPost = new HttpPost(url); try { httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8"); httpPost.setHeader("SOAPAction", SOAPAction); StringEntity data = new StringEntity(soap, Charset.forName("UTF-8")); httpPost.setEntity(data); CloseableHttpResponse response = closeableHttpClient .execute(httpPost); HttpEntity httpEntity = response.getEntity(); if (httpEntity != null) { // 打印響應內容 retStr = EntityUtils.toString(httpEntity, "UTF-8"); System.err.println("response:" + retStr); } // 釋放資源 closeableHttpClient.close(); } catch (Exception e) { e.printStackTrace(); } return retStr; }
接下來需要根據返回的xml格式數據解析為Json格式,我們可以用Postman測試WebService接口,查看數據返回格式,如下圖所示:
點擊Send,返回的數據格式如下圖所示:
數據太多,這里我給出返回的縮減的結構數據,如下
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <AAFlow002yResponse xmlns="http://tempuri.org/"> <AAFlow002yResult> <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="AAFlow002" msdata:UseCurrentLocale="true"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="AAFlow002"> <xs:complexType> <xs:sequence> <xs:element name="F1000" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <DocumentElement xmlns=""> <AAFlow002 diffgr:id="AAFlow0021" msdata:rowOrder="0"> <F1000>2596</F1000> </AAFlow002> </DocumentElement> </diffgr:diffgram> </AAFlow002yResult> </AAFlow002yResponse> </soap:Body> </soap:Envelope>
根據上面的信息,編寫解析xml數據轉換為Json格式數據代碼如下:
/** * 解析webservice的返回結果,將xml解析為json格式數據 * @param xmlStr xml內容 * @return */ public static JSONObject xml2Json(String xmlStr) throws DocumentException { Document doc = DocumentHelper.parseText(xmlStr); Element root = doc.getRootElement(); Element body = root.element("Body"); Element response = body.element("AAFlow002yResponse"); Element result = response.element("AAFlow002yResult"); Element diffgram = result.element(new QName("diffgram", Namespace.get("urn:schemas-microsoft-com:xml-diffgram-v1"))); Element documentElement = diffgram.element("DocumentElement"); Element aaFlow002 = documentElement.element("AAFlow002"); JSONObject jsonObject = new JSONObject(); Iterator<Element> iterator = aaFlow002.elementIterator(); while (iterator.hasNext()) { Element element = iterator.next(); jsonObject.put(element.getName(), element.getText()); } return jsonObject; }
通過HttpClient的方式調用WebService接口,缺點是需要自己編寫解析xml的代碼,而WebServiceTemplate的方式可以自動解析為對應的Java類,但是個人更偏向于使用HttpClient的方式調用WebService接口,WebServiceTemplate方式,代碼復雜度比較高,耦合性太強。
到此這篇關于SpringBoot調用第三方WebService接口的兩種方法的文章就介紹到這了,更多相關SpringBoot調用WebService接口內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java 創(chuàng)建動態(tài)類和查看方法列表信息的實例
這篇文章主要介紹了 Java 創(chuàng)建動態(tài)類和查看方法列表信息的實例的相關資料,需要的朋友可以參考下2017-06-06