webservice框架有很多,比如axis、axis2、cxf、xFire等等,做服務端和做客戶端都可行,個人感覺使用這些框架的好處是減少了對於接口信息的解析,最主要的是減少了對於傳遞於網絡中XML的解析,代價是你不得不在你的框架中添加對於這些框架的依賴。個人觀點是:服務端使用這些框架還行,如果做客戶端,沒必要使用這些框架,只需使用httpclient即可。
一、創建並發布一個簡單的webservice應用
1、webservice 代碼:
import javax.jws.WebMethod; import javax.jws.WebService; import javax.xml.ws.Endpoint; @WebService public class HelloWorld { @WebMethod public String sayHello(String str){ System.out.println("get Message..."); String result = "Hello World, "+str; return result; } public static void main(String[] args) { System.out.println("server is running"); String address="http://localhost:9000/HelloWorld"; Object implementor =new HelloWorld(); Endpoint.publish(address, implementor); } }
2、運行項目,並訪問 "http://localhost:9000/HelloWorld?wsdl",得到wsdl文件,說明webservice發布成功
例如天氣的wsdl:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
二、客戶端訪問webservice
1、通過 HttpClient 及 HttpURLConnection 發送SOAP請求,代碼如下:
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.io.IOUtils; public class TestHelloWrold { public static void main(String[] args) throws Exception { String wsdl = "http://localhost:9000/HelloWorld?wsdl"; int timeout = 10000; StringBuffer sb = new StringBuffer(""); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sb.append("<soap:Envelope " + "xmlns:api='http://demo.ls.com/' " + "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("<soap:Body>"); sb.append("<api:sayHello>"); sb.append("<arg0>ls</arg0>"); sb.append("</api:sayHello>"); sb.append("</soap:Body>"); sb.append("</soap:Envelope>"); // HttpClient發送SOAP請求 System.out.println("HttpClient 發送SOAP請求"); HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod(wsdl); // 設置連接超時 client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout); // 設置讀取時間超時 client.getHttpConnectionManager().getParams().setSoTimeout(timeout); // 然后把Soap請求數據添加到PostMethod中 RequestEntity requestEntity = new StringRequestEntity(sb.toString(), "text/xml", "UTF-8"); //設置請求頭部,否則可能會報 “no SOAPAction header” 的錯誤 postMethod.setRequestHeader("SOAPAction",""); // 設置請求體 postMethod.setRequestEntity(requestEntity); int status = client.executeMethod(postMethod); // 打印請求狀態碼 System.out.println("status:" + status); // 獲取響應體輸入流 InputStream is = postMethod.getResponseBodyAsStream(); // 獲取請求結果字符串 String result = IOUtils.toString(is); System.out.println("result: " + result); // HttpURLConnection 發送SOAP請求 System.out.println("HttpURLConnection 發送SOAP請求"); URL url = new URL(wsdl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8"); conn.setRequestMethod("POST"); conn.setUseCaches(false); conn.setDoInput(true); conn.setDoOutput(true); conn.setConnectTimeout(timeout); conn.setReadTimeout(timeout); DataOutputStream dos = new DataOutputStream(conn.getOutputStream()); dos.write(sb.toString().getBytes("utf-8")); dos.flush(); BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); String line = null; StringBuffer strBuf = new StringBuffer(); while ((line = reader.readLine()) != null) { strBuf.append(line); } dos.close(); reader.close(); System.out.println(strBuf.toString()); } }
響應報文如下:
<?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:sayHelloResponse xmlns:ns2="http://demo.ls.com/"> <return>Hello World, ls</return> </ns2:sayHelloResponse> </S:Body> </S:Envelope>
SOAP的請求報文的格式是怎么來的呢?
(1)可用Eclipse測試WSDL文件,則可得到想要的SOAP請求及響應報文,具體步驟如下圖:
第一步:
第二步:
通過第一步,會在瀏覽器打開如下的頁面
(2)saopui工具拿到soap報文
soapUI是一個開源測試工具,通過soap/http來檢查、調用、實現Web Service的功能/負載/符合性測試。該工具既可作為一個單獨的測試軟件使用,也可利用插件集成到Eclipse,maven2.X,Netbeans 和intellij中使用。soapUI pro是soapUI的商業非開源版本,實現的 功能較開源的soapUI更多。
a、首先得安裝soapUI 4.5.2,安裝后打開,截圖如下:
b、右鍵點擊“Projects”創建工程,截圖如下:
c、雙擊展開左側創建的工程下所有節點,最后雙擊“Request 1”節點,在右側即可拿到soap格式消息,這個就是我們后面作為客戶端調用服務端的報文內容,截圖如下:
2、生成客戶端代碼訪問
a、通過 "wsimport"(JDK自帶)命令生成客戶端代碼。進入命令行模式,執行 wsimport -s . http://localhost:9000/HelloWorld?wsdl,就會在當前目錄下生成客戶端代碼。附圖:
b、通過Eclipse生成客戶端代碼
(1).生成本地代碼后可以直接調用,比如調用天氣webservice接口:
package hanwl.TestDemo; import java.rmi.RemoteException; import javax.xml.rpc.ServiceException; import cn.com.WebXml.WeatherWebService; import cn.com.WebXml.WeatherWebServiceLocator; import cn.com.WebXml.WeatherWebServiceSoap; public class TestWebservice { public static void main(String[] args) { WeatherWebService weatherWebService = new WeatherWebServiceLocator(); WeatherWebServiceSoap weatherWebServiceSoap = null; try { weatherWebServiceSoap = weatherWebService.getWeatherWebServiceSoap(); } catch (ServiceException e) { // TODO Auto-generated catch block e.printStackTrace(); } String[] cityweather = null; //String[] city={"北京","上海","深圳","廣州"}; try { cityweather = weatherWebServiceSoap.getWeatherbyCityName("北京");//不輸入默認為上海市 } catch (RemoteException e) { e.printStackTrace(); } for(String s :cityweather){ System.out.println(s); System.out.println("------------------------"); } } }
(2).httpclient作為客戶端調用天氣webservice
package hanwl.TestDemo; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.io.IOUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.xml.sax.InputSource; public class TestWebservice2 { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub String wsdl = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl"; int timeout = 1000; StringBuffer sb = new StringBuffer(""); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sb.append("<soapenv:Envelope " + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " + " xmlns:q0='http://WebXml.com.cn/' " + " xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + " xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' >"); sb.append("<soapenv:Body>"); sb.append("<q0:getWeatherbyCityName>"); sb.append("<q0:theCityName>唐山</q0:theCityName> "); sb.append("</q0:getWeatherbyCityName>"); sb.append("</soapenv:Body>"); sb.append("</soapenv:Envelope>"); // HttpClient發送SOAP請求 System.out.println("HttpClient 發送SOAP請求"); HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod(wsdl); // 設置連接超時 client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout); // 設置讀取時間超時 client.getHttpConnectionManager().getParams().setSoTimeout(timeout); // 然后把Soap請求數據添加到PostMethod中 RequestEntity requestEntity = new StringRequestEntity(sb.toString(), "text/xml", "UTF-8"); //設置請求頭部,否則可能會報 “no SOAPAction header” 的錯誤 //postMethod.setRequestHeader("SOAPAction",""); // 設置請求體 postMethod.setRequestEntity(requestEntity); int status = client.executeMethod(postMethod); // 打印請求狀態碼 System.out.println("status:" + status); // 獲取響應體輸入流 InputStream is = postMethod.getResponseBodyAsStream(); // 獲取請求結果字符串 String result = IOUtils.toString(is); Document dc = strXmlToDocument(result); // Element root = dc.getRootElement(); // System.out.println(root.getName()); // System.out.println("result: " + result); } public static Document strXmlToDocument(String parseStrXml){ Document document = null; try { document = DocumentHelper.parseText(parseStrXml); Element root = document.getRootElement(); List<Element> list = root.elements(); getElement(list); } catch (DocumentException e) { e.printStackTrace(); } return document; } private static void getElement(List<Element> sonElemetList) { // Map<String,String> map = new HashMap<String, String>(); for (Element sonElement : sonElemetList) { if (sonElement.elements().size() != 0) { System.out.println(sonElement.getName() + ":"); getElement(sonElement.elements()); }else{ System.out.println(sonElement.getName() + ":"+ sonElement.getText()); } } } }
三、總結
優點:
1.使用httpclient作為客戶端調用webservice,不用關注繁瑣的webservice框架,只需找到SOAP消息格式,添加httpclient依賴就行。
2.使用httpclient調用webservice,建議采用soap1.1方式調用,經測試使用soap1.1方式能調用soap1.1和soap1.2的服務端。
缺點:
唯一的缺點是,你得自己解析返回的XML,找到你關注的信息內容。
參考地址:https://blog.csdn.net/zilong_zilong/article/details/53932667
https://blog.csdn.net/gzxdale/article/details/74242359