標籤:detail doc img ringbuf utf-8 模糊 blog efault 頭資訊
寫在前面:
調用webservice的方式有很多:1.直接在用戶端使用工具產生用戶端代碼,將代碼拷進項目中調用即可;2.使用對應的webservice架構來進行調用,比如如果我們我的服務端開發用的是axis,那麼我在用戶端也可以匯入相應的axis的jar包,然後用它相關的方法來進行調用;3.js調用;4.URLConnection調用。上面的前兩種方式個人認為比較適用於服務端與用戶端都是java開發系統,如果是不同語言的調用那就不好說了。而第三種與第四種的方式其實差不多,如果在jsp頁面中就要調用介面,就用js這種方式,如果需要在後台寫程式來調用,就比較推薦URLConnection了(現在只是會用,其實它的一些原理什麼的我還是很模糊,比如這種方式應該是http??調用??,還不是很清楚呢)
最近項目要開發webservice介面,但是jdk是1.4。故選擇了axis1.4來進行開發(只有這個比較適合項目的環境)。
這裡我也是用的java語言來做測試的,是可以調用的。解析服務端返回的資料需要用到相關jar包:
代碼:
package edu.hue.client;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.StringReader;import java.net.HttpURLConnection;import java.net.ProtocolException;import java.net.URL;import java.net.URLConnection;import java.util.List;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader;public class XMLClient2 { public static void main(String[] args) { try { //建立url地址 URL url = new URL("http://10.203.138.82:8080/test_axis3/services/sayHello?wsdl"); //開啟串連 URLConnection conn = url.openConnection(); //轉換成HttpURL HttpURLConnection httpConn = (HttpURLConnection) conn; System.setProperty("sun.net.client.defaultConnectTimeout", "30000"); System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //開啟輸入輸出的開關 httpConn.setDoInput(true); httpConn.setDoOutput(true); //post提交不能有緩衝 httpConn.setUseCaches(false); //佈建要求方式 httpConn.setRequestMethod("POST"); //佈建要求的頭資訊 httpConn.setRequestProperty("Content-type", "text/xml;charset=UTF-8"); //設定 SOAPAction Header 不然 報錯 沒有這個soapaction header httpConn.setRequestProperty("SOAPAction", ""); //拼接請求訊息 這裡的請求訊息體 直接用介面測試載入器 soapui 來擷取 然後拼接以下 注意雙引號這裡要轉義成\" String data = "<soapenv:Envelope xmlns:soapenv=" + "\"http://schemas.xmlsoap.org/soap/envelope/\" " + "xmlns:ser=\"http://server.hue.edu/\" " + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" //+"<soapenv:Header />" +"<soapenv:Body>" +"<ser:say soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +"<name xsi:type=\"soapenc:string\" xs:type=\"type:string\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xs=\"http://www.w3.org/2000/XMLSchema-instance\">" +"小蚊子qq:513996980" //這裡是直接在soapui中複製過來的所以它的請求訊息體比較長 也可以用下面這種 注釋的方式來拼接 +"</name>" +"</ser:say>" +"</soapenv:Body>" +"</soapenv:Envelope>"; /* 下面這種請求訊息體更為簡單 經過測試也可以成功 它的方法名 參數名 都很簡潔 * 但是為了保險 希望大家在寫請求訊息體的時候用 介面測試載入器去擷取比如soapui 然後直接複製過來 String data = "<soapenv:Envelope xmlns:soapenv=" + "\"http://schemas.xmlsoap.org/soap/envelope/\" " + "xmlns:ser=\"http://server.hue.edu/\" " + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +"<soapenv:Header />" +"<soapenv:Body>" +"<ser:say >" +"<name>小蚊子qq:513996980</name>" +"</ser:say>" +"</soapenv:Body>" +"</soapenv:Envelope>";*/ //獲得輸出資料流 OutputStream out = httpConn.getOutputStream(); //發送資料 這裡注意要帶上編碼utf-8 不然 不能傳遞中文參數過去 out.write(data.getBytes("UTF-8")); //判斷請求成功 if(httpConn.getResponseCode() == 200){ System.out.println("調用成功....."); //獲得輸入資料流 InputStream in = httpConn.getInputStream(); //使用輸入資料流的緩衝區 BufferedReader reader = new BufferedReader(new InputStreamReader(in,"UTF-8")); StringBuffer sb = new StringBuffer(); String line = null; //讀取輸入資料流 while((line = reader.readLine()) != null){ sb.append(line); } //建立sax的讀取器 這裡需要匯入相應的jar包 SAXReader saxReader = new SAXReader(); //建立文檔對象 Document doc = saxReader.read(new StringReader(sb.toString())); //獲得請求響應return元素 這裡可根據介面測試載入器查看你的相應訊息體的傳回值的節點是什麼名稱 我這裡是sayReturn List eles = doc.selectNodes("//sayReturn"); for(int i=0;i<eles.size();i++){ Element ele = (Element)eles.get(i); System.out.println(ele.getText()); } System.out.println(sb.toString()); }else{ //調用不成功 列印錯誤的資訊 //獲得輸入資料流 InputStream err = httpConn.getErrorStream(); //使用輸入資料流的緩衝區 BufferedReader reader = new BufferedReader(new InputStreamReader(err,"UTF-8")); StringBuffer sb = new StringBuffer(); String line = null; //讀取輸入資料流 while((line = reader.readLine()) != null){ sb.append(line); } System.out.println("返回錯誤碼:"+httpConn.getResponseCode()); System.out.println("返回的結果:"+sb.toString()); } } catch (Exception e) { e.printStackTrace(); }}}
上面是用戶端調用的代碼,服務端這裡就不多貼了,就只是一個方法,裡面有一個String類型的參數。
問題總結:
1.報錯誤 說http response result code 500:
java.io.IOException: Server returned HTTP response code: 500 for URL: http://10.203.138.82:8080/test_axis/services/sayHello
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
這裡的500錯誤 一般都是你的代碼有問題 哪裡可能寫的有點不對 這個時候就要仔細仔細再仔細 然後嘗試用不同的方式去排除錯誤所在的地方 也要多百度 多查 ,這裡我出現這個問題 是因為把輸入資料流寫在輸出資料流的前面(對於用戶端,應該是先寫輸出資料流之後,再寫輸入資料流get.InputStream())
2.針對axis1.4的bug:AxisFault faultCode: {http://xml.apache.org/axis/}Client.NoSOAPAction faultSubcode: faultString: no SOAPAction header! faultActor: faultNode: faultDetail: {http://xml.apache.org/axis/}stackTrace:no SOAPAction header!
no SOAPAction header! 這裡可以注意 如果報這個錯 加上一行代碼就好了啦 當初為了這個錯誤 幾乎看了一兩天的部落格文章 但是卻沒有人告訴具體的代碼解決辦法(有兩種解決辦法1:在用戶端加上soapaction,其具體內容不重要,寫一個空的字串也是可以的 2:服務端重寫寫一個servlet,與axisServlet一樣,並重新改寫裡面的getSoapAction()方法,這裡推薦只第一種,畢竟這個也算不上是axis的bug)
//設定 SOAPAction Header 不然 報錯 沒有這個soapaction header
httpConn.setRequestProperty("SOAPAction", "");
3.如果用戶端傳遞參數為中文就報錯:變為位元組數組的時候加上UTF-8
//獲得輸出資料流
OutputStream out = httpConn.getOutputStream();
//發送資料 這裡注意要帶上編碼utf-8 不然 不能傳遞中文參數過去
out.write(data.getBytes("UTF-8"));
疑問:
如果方法沒有參數 需要怎麼調用???在這裡 之前 跨平台 調用wcf開發的.net系統的時候 調用的介面方法是不需要傳遞參數的 但是也傳了一個空的字串過去就好了 也沒有寫什麼soap請求訊息體什麼的 但是這裡因為是webservice 它是基於soap的 所以這裡傳遞資料 不管有沒有參數 應該都是要寫上訊息請求體的 所以這裡需要注意一下
比如:
// 但是為了保險 希望大家在寫請求訊息體的時候用 介面測試載入器去擷取比如soapui 然後直接複製過來 String data = "<soapenv:Envelope xmlns:soapenv=" + "\"http://schemas.xmlsoap.org/soap/envelope/\" " + "xmlns:ser=\"http://server.hue.edu/\" " + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +"<soapenv:Header />" +"<soapenv:Body>" +"<ser:say >" //比如這裡要調用的方法沒有參數 就直接不用寫就好 但是這個訊息體 應該還是要的 +"</ser:say>" +"</soapenv:Body>" +"</soapenv:Envelope>";
使用URLConnection調用axis1.4開發的webservice