Web Service 運(yùn)行原理詳細(xì)介紹
利用清明小假期,溫習(xí)了一遍Web Service的相關(guān)內(nèi)容,對其工作原理進(jìn)行了簡要總結(jié)。以供有需求的朋友和自己日后參考。文章若有不當(dāng)之處,敬請朋友們提出寶貴建議,以求共勉。
Web服務(wù)中,我們應(yīng)該首先了解相關(guān)的術(shù)語含義:WSDL、UDDI....相關(guān)術(shù)語方面的介紹在此不再贅述,重點(diǎn)放在原理上。
在Web服務(wù)中,存在三個角色:服務(wù)提供者、服務(wù)請求者和服務(wù)中介,三者之間的關(guān)系如圖1-1所示
實(shí)現(xiàn)一個完整的Web服務(wù)包括以下步驟:
◆ Web服務(wù)提供者設(shè)計實(shí)現(xiàn)Web服務(wù),并將調(diào)試正確后的Web服務(wù)通過Web服務(wù)中介者發(fā)布,并在UDDI注冊中心注冊; (發(fā)布)
◆ Web服務(wù)請求者向Web服務(wù)中介者請求特定的服務(wù),中介者根據(jù)請求查詢UDDI注冊中心,為請求者尋找滿足請求的服務(wù); (發(fā)現(xiàn))
◆ Web服務(wù)中介者向Web服務(wù)請求者返回滿足條件的Web服務(wù)描述信息,該描述信息用WSDL寫成,各種支持Web服務(wù)的機(jī)器都能閱讀;(發(fā)現(xiàn))
◆ 利用從Web服務(wù)中介者返回的描述信息(WSDL)生成相應(yīng)的SOAP消息,發(fā)送給Web服務(wù)提供者,以實(shí)現(xiàn)Web服務(wù)的調(diào)用;(綁定)
◆ Web服務(wù)提供者按SOAP消息執(zhí)行相應(yīng)的Web服務(wù),并將服務(wù)結(jié)果返回給Web服務(wù)請求者。(綁定)

圖1-1 Web service的體系結(jié)構(gòu)
注:WSDL的作用就是一個Web服務(wù)說明書。服務(wù)請求者根據(jù)此WSDL生成相應(yīng)的SOAP消息,服務(wù)提供者在收到SOAP請求消息后,進(jìn)行服務(wù)的綁定。
以下代碼是在web.xml中的servlet配置
<!-- 在向servlet或JSP頁面制定初始化參數(shù)或定制URL時,必須首先命名servlet或JSP頁面。Servlet元素就是用來完成此項(xiàng)任務(wù)的。 -->
<servlet>
<servlet-name>UserService</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<!-- 標(biāo)記容器是否在啟動的時候就加載這個servlet(實(shí)例化并調(diào)用其init()方法;正數(shù)的值越小,該servlet的優(yōu)先級越高,應(yīng)用啟動時就越先加載 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 服務(wù)器一般為servlet提供一個缺省的URL:http://host/webAppPrefix/servlet/ServletName。
但是,常常會更改這個URL,以便servlet可以訪問初始化參數(shù)或更容易地處理相對URL。在更改缺省URL時,使用servlet-mapping元素。 -->
<servlet-mapping>
<servlet-name>UserService</servlet-name>
<!-- 描述了相對于Web應(yīng)用的根目錄的URL。url-pattern元素的值必須以斜杠(/)起始。 -->
<url-pattern>/user</url-pattern>
</servlet-mapping>
紅色代碼部分很重要,會在Web容器啟動的時候加載相應(yīng)的servlet。綠色部分為該服務(wù)的外部接口。以此找到相應(yīng)的jax-ws.xml文件(如下所示)
<endpoint name="UserPort" implementation="cn.ujn.service.UserService"
url-pattern="/user">
</endpoint>
進(jìn)而綁定到相關(guān)的相應(yīng)的實(shí)現(xiàn)類cn.ujn.service.UserService中??蛻舳税l(fā)送的SOAP請求消息消息體body中包含有客戶端所請求的方法名和參數(shù)信息。
以下為客戶端封裝的soap消息體(以Json方式與服務(wù)端進(jìn)行數(shù)據(jù)傳輸)(SOAP Rerquest Envelope):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ujn.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <soapenv:Body>
- <q0:login>
<arg0>{"username":"shq","password":"shq"}</arg0>
</q0:login>
</soapenv:Body>
</soapenv:Envelope>
以下為SOAP1.1協(xié)議調(diào)用Web服務(wù)
/**
* 通過SOAP1.1協(xié)議調(diào)用Web服務(wù)
*
* text/xml 這是基于soap1.1協(xié)議
*
* @param wsdl WSDL路徑
* @param method方法名
* @param namespace命名空間
* @param headerParameters 頭參數(shù)
* @param bodyParameters 體參數(shù)
* @param isBodyParametersNS 體參數(shù)是否有命名空間
* @return String
* @throws Exception
*/
public static String invokeBySoap11(String wsdl, String method,
String namespace, Map<String, String> headerParameters,
Map<String, String> bodyParameters, boolean isBodyParametersNS)
throws Exception {
StringBuffer soapOfResult = null;
// 去除 ?wsdl,獲取方法列表
int length = wsdl.length();
wsdl = wsdl.substring(0, length - 5);
//以字符串為參數(shù)創(chuàng)建URL實(shí)例
URL url = new URL(wsdl);
//創(chuàng)建連接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//設(shè)置請求方式
conn.setRequestMethod("POST");
//如果打算使用 URL連接進(jìn)行輸入,則將 DoInput 標(biāo)志設(shè)置為 true
conn.setDoInput(true);
//如果打算使用 URL連接進(jìn)行輸出,則將 DoInput 標(biāo)志設(shè)置為 true
conn.setDoOutput(true);
//主要是設(shè)置HttpURLConnection請求頭里面的屬性(K-V)
conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
//獲取輸入流(相對于客戶端來說,使用的是OutputStream)
OutputStream out = conn.getOutputStream();
// 獲取soap1.1版本消息
StringBuilder sb = new StringBuilder();
sb.append("<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/\" ");
sb.append("xmlns:ns0=\"" + namespace + "\"");
sb.append(">");
//拼裝消息頭
if (headerParameters != null) {
sb.append("<soap:Header>");
for (Entry<String, String> headerParameter : headerParameters
.entrySet()) {
sb.append("<ns0:");
sb.append(headerParameter.getKey());
sb.append(">");
sb.append(headerParameter.getValue());
sb.append("</ns0:");
sb.append(headerParameter.getKey());
sb.append(">");
}
sb.append("</soap:Header>");
}
//拼裝消息體
sb.append("<soap:Body><ns0:");
sb.append(method);
sb.append(">");
// 輸入?yún)?shù)
if (bodyParameters != null) {
for (Entry<String, String> inputParameter : bodyParameters
.entrySet()) {
if (isBodyParametersNS) {
sb.append("<ns0:");
sb.append(inputParameter.getKey());
sb.append(">");
sb.append(inputParameter.getValue());
sb.append("</ns0:");
sb.append(inputParameter.getKey());
sb.append(">");
} else {
sb.append("<");
sb.append(inputParameter.getKey());
sb.append(">");
sb.append(inputParameter.getValue());
sb.append("</");
sb.append(inputParameter.getKey());
sb.append(">");
}
}
}
sb.append("</ns0:");
sb.append(method);
sb.append("></soap:Body></soap:Envelope>");
//測試用
System.out.println(sb.toString());
//寫入SOAP消息(相對于客戶端來說,使用的是out.write())
out.write(sb.toString().getBytes());
//獲取服務(wù)器端的相應(yīng)
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
soapOfResult = new StringBuffer();
//從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲在緩沖區(qū)數(shù)組 b 中。以整數(shù)形式返回實(shí)際讀取的字節(jié)數(shù)
//如果因?yàn)榱魑挥谖募┪捕鴽]有可用的字節(jié),則返回值 -1;
while ((len = is.read(b)) != -1) {
//Converts the byte array to a string using the named charset.
String s = new String(b, 0, len, "UTF-8");
soapOfResult.append(s);
}
}
conn.disconnect();
return soapOfResult == null ? null : soapOfResult.toString();
}
注:在客戶端發(fā)送SOAP請求消息后便處于阻塞狀態(tài)。直至服務(wù)端返回狀態(tài)碼。
以下為服務(wù)端進(jìn)行響應(yīng)(SOAP Response Envelope):
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> -<S:Body> -<ns2:loginResponse xmlns:ns2="http://ujn.cn/"> <return>1</return> </ns2:loginResponse> </S:Body> </S:Envelope>
客戶端接收到服務(wù)端發(fā)來的Json數(shù)據(jù)后會進(jìn)行相應(yīng)的解析操作。如下:
// 將Soap協(xié)議進(jìn)行解析(DOM解析只能用于解析XML文檔類型,而SOAP消息就是采用XML數(shù)據(jù)格式)
Document doc = XmlUtil.string2Doc(result);
Element ele = (Element) doc.getElementsByTagName("return").item(0);
方法中使用到的string2Doc()方法體如下:
public static Document string2Doc(String str) {
//將XML文檔解析成DOM樹
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document = null;
DocumentBuilder build;
if (str == null || str.equals("")) {
return null;
}
try {
InputStream bais = new ByteArrayInputStream(str.getBytes("UTF-8"));
build = factory.newDocumentBuilder();
//Parse the content of the given InputStream as an XML document and return a new DOM Document object.
document = build.parse(bais);
} catch (Exception e) {
e.printStackTrace();
}
return document;
}
根據(jù)返回結(jié)果,客戶端再進(jìn)行相應(yīng)的處理。
以上是web服務(wù)的基本工作原理。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
- java webservice上傳下載文件代碼分享
- ASP.NET使用WebService實(shí)現(xiàn)天氣預(yù)報功能
- C# WebService發(fā)布以及IIS發(fā)布
- ASP.NET調(diào)用WebService服務(wù)的方法詳解
- jQuery中通過ajax調(diào)用webservice傳遞數(shù)組參數(shù)的問題實(shí)例詳解
- ajax跨域調(diào)用webservice的實(shí)現(xiàn)代碼
- js調(diào)用webservice構(gòu)造SOAP進(jìn)行身份驗(yàn)證
- PHP使用SOAP擴(kuò)展實(shí)現(xiàn)WebService的方法
- ASP調(diào)用WebService轉(zhuǎn)化成JSON數(shù)據(jù),附j(luò)son.min.asp
相關(guān)文章
Java實(shí)現(xiàn)圖片與Base64編碼互轉(zhuǎn)
這篇文章主要介紹了Java中實(shí)現(xiàn)圖片與Base64編碼互轉(zhuǎn)的方法,比較實(shí)用,需要的朋友可以參考下。2016-06-06
Java中注解@JsonFormat與@DateTimeFormat的使用
從數(shù)據(jù)庫獲取時間傳到前端進(jìn)行展示的時候,我們有時候可能無法得到一個滿意的時間格式的時間日期,本文主要介紹了Java中注解@JsonFormat與@DateTimeFormat的使用,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
idea插件生成jpa實(shí)體類的實(shí)現(xiàn)示例
本文主要介紹了idea插件生成jpa實(shí)體類的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
SpringBoot參數(shù)校驗(yàn)的最佳實(shí)戰(zhàn)教程
開發(fā)過程中,后臺的參數(shù)校驗(yàn)是必不可少的,下面這篇文章主要給大家介紹了關(guān)于SpringBoot參數(shù)校驗(yàn)的最佳實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08
SpringBoot教程_創(chuàng)建第一個SpringBoot項(xiàng)目
這篇文章主要介紹了SpringBoot教程_創(chuàng)建第一個SpringBoot項(xiàng)目,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
myeclipse導(dǎo)出可運(yùn)行jar包簡介
這篇文章主要介紹了myeclipse導(dǎo)出可運(yùn)行jar包簡介,具有一定參考價值,需要的朋友可以了解下。2017-11-11
SpringBoot自動裝配Condition的實(shí)現(xiàn)方式
這篇文章主要介紹了SpringBoot自動裝配Condition的實(shí)現(xiàn)方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
解決JPA?save()方法null值覆蓋掉mysql預(yù)設(shè)的默認(rèn)值問題
這篇文章主要介紹了解決JPA?save()方法null值覆蓋掉mysql預(yù)設(shè)的默認(rèn)值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11

