網上查找資料總結有以下實現方式
1)使用命令生成接口和實體類,如wsimport -p . -keep http://localhost:8080/hello?wsdl,直接調取接口使用,但是生成了一大堆文件
2)xfire,後續版本cxf,個人建議使用,兼容大多數
3)axis,後續版本axis2,調用webservice感覺兼容性差,但是用來發布webservice感覺很方便,axis2本身就是一個web服務,只需要把寫好的.class方法文件往服務路徑裏面一扔一個webservice就對外發布了
4)直接使用http請求,get和post方法都可以,就是自己封裝成envelop的xml格式參數,get方法需要得到輸入流往裏面寫入參數,post方法可以直接將xml參數作爲實體傳參,我使用post方法實現。
下面是我的做法
1)先考慮使用cxf,因爲cxf調用起來真心的簡單。
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.9</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.1.9</version> </dependency>下面是調用demo,如果對同一個webservice服務多次調用,可以將client靜態緩存。
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient("http://localhost:9003/soap?wsdl"); Object[] o=new Object[]{"arg0","arg1"};//入參按照方法的順序填充 try { Object[] result = client.invoke("getUser",o);//getUser是方法名,client.invoke("getUser","liu","fang"); //輸出調用結果 System.out.println(result[0].getClass()); System.out.println(result[0].toString()); System.out.println(JSONObject.fromObject(result[0]).toString()); } catch (Exception e) { e.printStackTrace(); }
2)cxf調不通的,一般是C#寫的webservice,1)入參使用了ref這種結構 2)出參解析的時候多了一個實體類的描述,在這種情況我直接用http請求自己解析xml實現。
網上有很多demo
用org.apache.httpcomponents httpcore的HttpWebRequest實現http://www.cnblogs.com/hfliyi/archive/2012/09/16/2687843.html
用HttpURLConnection實現 http://blog.csdn.net/bjxyj/article/details/46725899 http://blog.csdn.net/bjxyj
我現在使用httpClient的CloseableHttpClient實現,沒有啓用連接池
public static String doHttpPost(String apiUrl, String content,String contentType) throws Exception{ CloseableHttpClient httpClient = HttpClients.createDefault(); String httpStr = null; HttpPost httpPost = new HttpPost(apiUrl); CloseableHttpResponse response = null; try { StringEntity stringEntity = new StringEntity(content, "UTF-8"); stringEntity.setContentEncoding("UTF-8"); stringEntity.setContentType(contentType); httpPost.setEntity(stringEntity); response = httpClient.execute(httpPost); httpStr = EntityUtils.toString(response.getEntity(), "UTF-8"); } catch (Exception e) { throw e; } finally { if (response != null) { try { EntityUtils.consume(response.getEntity()); } catch (IOException e) { e.printStackTrace(); } } } httpClient.close(); return httpStr; }
public static String doPost(String webserviceURL,Object[] objects) throws Exception { return doHttpPost(webserviceURL,buildXML(objects),"text/xml;charset=utf-8"); } public static String buildXML(Object[] objects){ StringBuilder sb = new StringBuilder("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://tempuri.org/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">");
sb.append("<soap:Header/>"); sb.append("<soap:Body>"); sb.append("<tns:getUser>");//我實際調用時方法名用objects[0] sb.append("<arg0>liu</arg0>");//我實際調用時參數1使用objects[1] sb.append("<arg1>fang</arg1>");//我實際調用時參數2使用objects[2] sb.append("</tns:getUser>");//我實際調用時使用objects[0] sb.append("</soap:Body>"); sb.append("</soap:Envelope>"); return sb.toString();} 注意調通的關鍵是xml參數,你可以使用soapUI工具進行調試
soap是引用信封envelope,參數值固定,soap可以修改成其它名字如soapenv,如果改成了soapenv後面的標籤中soap也需要修改
tns後面接的是命名空間,直接訪問?wsdl路徑就可以看到,沒有修改的話默認就是http://tempuri.org/,tns也可以改成其它的名字,如常見的tem,相應的後面的方法和參數標籤中也需要修改。關於入參,一般參數和方法的寫法一致也要加上tns:的前綴,但在我的demo中參數必須是arg0,arg1,arg2這種寫法才能取到值。
一般webservice要寫成這樣,如<tns:getUser><tns:firstname>liufang</tns:firstname><tns:lastname>fang</tns:lastname></tns:getUser>
xsd在本例中可以不用添加
我測試時發佈webservice採用最簡單的方法
public String getUser(String firstname,String lastname){ return firstname+" "+lastname; } public static void main(String[] args) { javax.xml.ws.Endpoint.publish("http://localhost:9003/soap", new NativeMethod()); System.out.println("werbservice publish success"); }