English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Web Serviceの運行原理の詳細な紹介

     清明の小休暇を利用して、Web Serviceの関連内容を温習し、その動作原理を簡単にまとめました。必要な方や自分自身の将来の参考に役立ててください。文章に不適切な点があれば、ぜひ貴重な意見をいただければ幸いです。

      Webサービスでは、まず以下の用語の意味を理解する必要があります:WSDL、UDDIなど。関連する用語の紹介はここでは省略し、原理に焦点を当てます。
Webサービスでは、以下の3つの役割が存在します:サービスプロバイダー、サービスリクエスト者、サービスメディエータ、三者の関係は以下の図に示されています1-1所示

    完全なWebサービスの実装には以下のステップが含まれます:

   ◆ WebサービスプロバイダーはWebサービスを実装し、テストが正常に行われた後のWebサービスをWebサービスメディエータを通じて公開し、UDDI登録センターに登録します;(公開)

   ◆ Webサービスリクエスト者は特定のサービスをWebサービスメディエータにリクエストし、メディエータはリクエストに基づいてUDDI登録センターをクエリし、リクエスト者に満足するサービスを見つけます;(発見)

   ◆ Webサービスメディエータは条件を満たすWebサービスの説明情報をWebサービスリクエスト者に返し、この説明情報はWSDLで書かれており、さまざまなWebサービスをサポートする機器で読み取れます;(発見)

   ◆ Webサービスメディエータから返される説明情報(WSDL)に基づいて相应的SOAPメッセージを生成し、Webサービスプロバイダーに送信して、Webサービスの呼び出しを実現します;(バインディング)

   ◆ WebサービスプロバイダーはSOAPメッセージに基づいて相应的Webサービスを実行し、サービス結果をWebサービスリクエスト者に返します。(バインディング)

  

図1-1 Webサービスのアーキテクチャ

     注:WSDLの役割はWebサービスの説明書です。サービスリクエスト者がこのWSDLに基づいて相应的SOAPメッセージを生成し、サービスプロバイダーがSOAPリクエストメッセージを受け取った後、サービスのバインディングを行います。

     以下のコードはweb.xml内のサーブレット設定です

  <!-- サーブレットやJSPページに初期化パラメータやカスタムURLを設定する際には、まずサーブレットやJSPページに名前を付けなければなりません。サーブレット要素はこのタスクを完了するために使用されます。 -->
  <servlet>
  <servlet-name>UserService</servlet-name>
  <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
  <!-- タグは、コンテナが起動時にこのservletをロードするかどうかを示しています(インスタンス化しinit()メソッドを呼び出します;正の値が小さいほど、servletの優先順位が高く、アプリケーションの起動時に早くロードされます -->
  <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- サーバーは、servletにデフォルトのURLを提供します:http://host/webAppPrefix/servlet/ServletNameを使用します。
   ただし、このURLはよく変更され、servletが初期化パラメータにアクセスしたり、相対URLをより簡単に処理するために変更されます。デフォルトのURLを変更する場合、servlet-mapping要素。 -->
  <servlet-mapping>
   <servlet-name>UserService</servlet-name>
   <!-- Webアプリケーションのルートディレクトリに対するURLを説明しています。-pattern要素の値は、スラッシュ(/)から始まる。 -->
   <url-pattern>/user</url-pattern>
  </servlet-mapping>
  赤いコード部分は非常に重要で、Webコンテナの起動時に対応するservletがロードされます。緑色部分はこのサービスの外部インターフェースです。これにより、対応するjax-ws.xmlファイル(以下の通り)
  <endpoint name="UserPort" implementation="cn.ujn.service.UserService"
    url-pattern="/user">
  </endpoint>

    进而绑定到相关的相应的实现类cn.ujn.service.UserService中。客户端发送的SOAP请求消息消息体body中包含有客户端所请求的方法名和参数信息。

    以下为客户端封装的soap消息体(以Json方式与服务端进行数据传输)(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プロトコルでWebサービスを呼び出します

/** 
* SOAPを通じて1.1プロトコルでWebサービスを呼び出します 
* 
* text/xml これはsoapに基づいています1.1プロトコル 
* 
* @param wsdl WSDLパス 
* @param methodメソッド名 
* @param namespaceネームスペース 
* @param headerParameters ヘッダパラメータ 
* @param bodyParameters 体パラメータ 
* @param isBodyParametersNS 体パラメータにネームスペースがあります 
* @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; 
//文字列をパラメータとしてURLインスタンスを作成します 
URL url = new URL(wsdl); 
//接続を作成します 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
//リクエスト方法を設定します 
conn.setRequestMethod("POST"); 
//URL接続で入力を使用する場合、DoInputフラグをtrueに設定します 
conn.setDoInput(true); 
//URL接続で出力を使用する場合、DoInputフラグをtrueに設定します 
conn.setDoOutput(true); 
//主にHttpURLConnectionのリクエストヘッダの属性を設定するためです(K-V) 
conn.setRequestProperty("Content"-Type", "text/xml; charset=utf-8"); 
//入力ストリームを取得(クライアントに対して、OutputStreamを使用しています)} 
OutputStream out = conn.getOutputStream(); 
// soapを取得1.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=\"" + ネームスペース + "\" 
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(>"); 
// 入力パラメータ 
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()); 
//サーバーの応答を取得 
int code = conn.getResponseCode(); 
if (code == 200) { 
InputStream is = conn.getInputStream(); 
byte[] b = new byte[1024]; 
int len = 0; 
soapOfResult = new StringBuffer(); 
//入力ストリームから一定量のバイトを読み取り、それをバッファーアレイbに格納します。実際に読み取ったバイト数を整数として返します 
//ストリームがファイルの最後に位置していない場合に利用可能なバイトがない場合の返値 -1; 
while ((len = is.read(b)) != -1) { 
//バイト配列を指定されたチャートセットを使用して文字列に変換します。  
String s = new String(b, 0, len, "UTF-8"); 
soapOfResult.append(s); 
} 
} 
conn.disconnect(); 
return soapOfResult == null ? null : soapOfResult.toString(); 
} 

    注:クライアントがSOAPリクエストメッセージを送信した後、ブロッキング状態になります。サーバーがステータスコードを返信するまで待機します。

    以下はサービス側の応答(SOAPレスポンスエンベロープ)です:

<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>

    クライアントがサーバーから送信されたJsonデータを受け取った後、対応する解析操作を行います。以下のようになります:

// Soapプロトコルを解析します(DOM解析はXMLドキュメントタイプのみに適用可能であり、SOAPメッセージはXMLデータ形式を使用しています) 
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"));-8")); 
build = factory.newDocumentBuilder(); 
//指定されたInputStreamの内容をXMLドキュメントとしてパースし、新しいDOM Documentオブジェクトを返します。  
document = build.parse(bais); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
return document; 
} 

    返される結果に基づいて、クライアントが対応する処理を行います。

    以上はウェブサービスの基本的な動作原理です。

    読んでいただきありがとうございます。皆様のサポートに感謝します!

おすすめ