Java发布webservice应用并发送SOAP请求调用
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