一、概念、原理
WebService的主要目标是跨平台(xml)的可互操作性。
场景:异构系统之间交换数据。访问其他部门的同构系统。实现应用之间的松耦合。 把可重复使用的应用程序组件作为服务来提供,比如天气预报。在不同的应用程序与平台之间来交换数据。
不适用场景:一台机器或一个局域网里面运行的同构应用程序。性能低。
Web services 使用 XML 来编解码数据,并使用 SOAP 来传输数据。
Web服务的体系结构是基于Web服务提供者、Web服务请求者、Web服务中介者(wsdl)三个角色和发布、发现、绑定三个动作构建的。
请求者利用wsdl描述SOAP(Simple Object Access Protocol,简单对象访问协议,)消息向Web服务提供者发送请求以获得服务
SOAP 是一种基于 XML 的简易协议,允许应用程序通过 HTTP 来交换信息。
WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用一个简单的 XML 文档来描述 Web Services 以及如何对它们进行访问。
<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Header> ... ... </soap:Header> <soap:Body> ... ... <soap:Fault> ... ... </soap:Fault> </soap:Body> </soap:Envelope>
二、 cxf
1、服务端:
服务端和客户端都使用版本:cxf-2.7.7,使用了如下几个包
package com.thrillerzw.springtest.cxf.server; import java.util.List; import javax.jws.WebService; import com.thrillerzw.springtest.cxf.User; /** * * webservice接口 * * @author thrillerzw * @date 2013年9月26日 */ @WebService public interface IHelloService { //字符串 public String sayHello(String username); //对象 public User getUser(long id); //list集合 public List<User> getList(); }
package com.thrillerzw.springtest.cxf.server; import java.util.ArrayList; import java.util.List; import javax.jws.WebService; import com.thrillerzw.springtest.cxf.User; /** * webservice实现类 * * @author thrillerzw * @date 2013年9月26日 */ @WebService(endpointInterface = "com.thrillerzw.springtest.cxf.server.IHelloService") public class HelloServiceImpl implements IHelloService { @Override public String sayHello(String username) { return "hello, " + username; } @Override public User getUser(long id) { User user = new User(); user.setId(id); user.setName("名字thrillerzw"); user.setAge(27); return user; } @Override public List<User> getList() { List<User> list = new ArrayList<User>(); if (list != null) { for (int i = 1; i <= 3; i++) { User user = new User(); user.setId(i); user.setName("名字thrillerzw" + i); user.setAge(20 + i); list.add(user); } } return list; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- ***注意*** 手动添加的内容: xmlns:jaxws="http://cxf.apache.org/jaxws" http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="helloService" implementor="com.thrillerzw.springtest.cxf.server.HelloServiceImpl" address="/helloService" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- Spring上下文配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/applicationContext-*.xml</param-value> </context-param> <!-- Spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- cxf --> <servlet> <servlet-name>CXFServlet</servlet-name> <display-name>CXFServlet</display-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> </web-app>
2、客户端:
生成客户端代码:
F:\apache-cxf-2.7.7\bin>wsdl2java -d src -client http://192.168.1.2/springtest
/ws/helloService?wsdl
手动创建src目录
拷贝生成的文件到工程,不需要拷贝IHelloService.java ,IHelloService_HelloServiceImplPort_Client.java 这2个文件。
package cxf.client; import java.util.List; import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.dynamic.DynamicClientFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.thrillerzw.springtest.cxf.server.IHelloService; import com.thrillerzw.springtest.cxf.server.User; /** * cxf客户端 * * @author thrillerzw * @date 2013年9月26日 */ public class CxfClient { public static void main(String[] args) { //直接调用字符串 DynamicClientFactory dcf = DynamicClientFactory.newInstance(); Client client = dcf.createClient("http://192.168.1.2/springtest/ws/helloService?wsdl"); Object[] reply=null; try { reply = client.invoke("sayHello", new Object[] { "thrillerzw" }); } catch (Exception e) { e.printStackTrace(); } System.out.println(reply[0]); try { reply = client.invoke("getUser", new Object[] { new Long(1) }); } catch (Exception e) { e.printStackTrace(); } System.out.println(reply[0]); //通过spring,调用字符串、对象、集合 System.out.println("spring---------------------"); ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-cxf-client.xml"); IHelloService helloService = (IHelloService) context.getBean("client"); System.out.println(helloService.sayHello("thrillerzw")); User user=helloService.getUser(20); System.out.println(user.getId()+" "+user.getName()+" "+user.getAge()); List<User> list= helloService.getList(); for(User u: list){ System.out.println(u.getId()+" "+u.getName()+" "+u.getAge()); } } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- ***注意*** 手动添加的内容: xmlns:jaxws="http://cxf.apache.org/jaxws" http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <bean id="client" class="com.thrillerzw.springtest.cxf.server.IHelloService" factory-bean="clientFactory" factory-method="create" /> <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.thrillerzw.springtest.cxf.server.IHelloService" /> <property name="address" value="http://192.168.1.2/springtest/ws/helloService" /> </bean> </beans>
输出:
hello, thrillerzw
com.thrillerzw.springtest.cxf.server.User@1f4cdd2
spring---------------------
hello, thrillerzw
20 名字thrillerzw 27
1 名字thrillerzw1 21
2 名字thrillerzw2 22
3 名字thrillerzw3 23
Apache cxf 学习笔记 http://wenku.baidu.com/view/ae7f5fa8d1f34693daef3e91.html
三、axis2
1 调用天气客户端
http://www.webxml.com.cn/WebServices/WeatherWebService.wsdl
package com.thrillerzw.springtest.axis2.client; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.soap.SOAP11Constants; import org.apache.axis2.Constants; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.client.Options; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.transport.http.HttpTransportProperties.ProxyProperties; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.XPath; import org.dom4j.io.SAXReader; public class WeatherTest { private static EndpointReference targetEPR = new EndpointReference( "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"); public OMElement getResult() throws Exception { ServiceClient sender = new ServiceClient(); sender.setOptions(buildOptions()); OMElement result = sender.sendReceive(buildParam()); // System.out.println(result); return result; } private static OMElement buildParam() { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace("http://WebXml.com.cn/", ""); OMElement data = fac.createOMElement("getWeatherbyCityName", omNs); OMElement inner = fac.createOMElement("theCityName", omNs); inner.setText("北京"); data.addChild(inner); return data; } private static Options buildOptions() { Options options = new Options(); options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI); options.setAction("http://WebXml.com.cn/getWeatherbyCityName"); options.setTo(targetEPR); // options.setProperty 如果不是通过代理上网,此句可省 // options.setProperty(HTTPConstants.PROXY, buildProxy()); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); return options; } /** * 本机采用代理服务器上网时,需要设置代理 * * @return */ public static ProxyProperties buildProxy() { ProxyProperties proxyProperties = new ProxyProperties(); proxyProperties.setProxyName("代理名称"); proxyProperties.setProxyPort(8080); return proxyProperties; } public static List<String> parseOMElement(OMElement element) { if (element == null) { return null; } Iterator<OMElement> iterator = element.getChildElements(); List<String> list = new ArrayList<String>(); OMElement result = null; Iterator<OMElement> childIte=null; while (iterator.hasNext()) { result = iterator.next(); childIte= result.getChildElements(); while (childIte.hasNext()) { OMElement elem = childIte.next(); list.add(elem.getText()); } } return list; } public static List<String> parseXml(String xml) { List<String> list = new ArrayList<String>(); try { Document document = DocumentHelper.parseText(xml); //方法一:遍历 /* Element root = document.getRootElement(); Element element=root.element("getWeatherbyCityNameResult"); List<Element> strList = element.elements("string"); for(Element e:strList){ list.add(e.getTextTrim()); }*/ //方法二:通过xpath查找 ,注意:设置namespace /* 如果没有namespace会简单很多,如下 * Node root = document.getRootElement(); * List<Element> elements=root.selectNodes("/getWeatherbyCityNameResponse/ns:getWeatherbyCityNameResult/ns:string"); */ Map map = new HashMap(); //ns自己定义 map.put("ns", "http://WebXml.com.cn/"); //根元素不是必须带ns: 或者 相对查找 ns:getWeatherbyCityNameResult/ns:string 或者 //ns:string XPath x = document .createXPath("/getWeatherbyCityNameResponse/ns:getWeatherbyCityNameResult/ns:string"); x.setNamespaceURIs(map); List<Element> nodelist = x.selectNodes(document); for(Element e:nodelist){ list.add(e.getText()); } } catch (DocumentException e) { e.printStackTrace(); } return list; } public static void main(String[] args) throws Exception { WeatherTest s = new WeatherTest(); OMElement oMElement = s.getResult(); System.out.println("------------------ parseOMElement"); List<String> list = parseOMElement(oMElement); for (String value : list) { System.out.println(value); } System.out.println("------------------ parseXml"); List<String> xmlList = parseXml(oMElement.toString()); for (String value : xmlList) { System.out.println(value); } } }
输出:
------------------ parseOMElement
直辖市
北京
54511
54511.jpg
2013-10-1 12:49:01
12℃/20℃
10月1日 多云转晴
北风3-4级
1.gif
0.gif
今日天气实况:气温:16℃;风向/风力:东北风 3级;湿度:89%;空气质量:良;紫外线强度:最弱
穿衣指数:较舒适,建议穿薄外套或牛仔裤等服装。
过敏指数:不易发,除特殊体质,无需担心过敏问题。
运动指数:较不宜,有较强降水,请在室内进行休闲运动。
洗车指数:不宜,有雨,雨水和泥水会弄脏爱车。
晾晒指数:不宜,有较强降水会淋湿衣物,不适宜晾晒。
旅游指数:一般,风稍大,较强降雨将给出行带来不便。
路况指数:湿滑,路面湿滑,车辆易打滑,减慢车速。
舒适度指数:舒适,白天不冷不热,风力不大。
空气污染指数:良,气象条件有利于空气污染物扩散。
紫外线指数:最弱,辐射弱,涂擦SPF8-12防晒护肤品。
9℃/23℃
10月2日 晴
北风3-4级转无持续风向微风
0.gif
0.gif
12℃/23℃
10月3日 晴
无持续风向微风
0.gif
0.gif
北京位于华北平原西北边缘,市中心位于北纬39度,东经116度xxx...
------------------ parseXml
直辖市
北京
54511
54511.jpg
2013-10-1 12:49:01
12℃/20℃
10月1日 多云转晴
北风3-4级
1.gif
0.gif
今日天气实况:气温:16℃;风向/风力:东北风 3级;湿度:89%;空气质量:良;紫外线强度:最弱
穿衣指数:较舒适,建议穿薄外套或牛仔裤等服装。
过敏指数:不易发,除特殊体质,无需担心过敏问题。
运动指数:较不宜,有较强降水,请在室内进行休闲运动。
洗车指数:不宜,有雨,雨水和泥水会弄脏爱车。
晾晒指数:不宜,有较强降水会淋湿衣物,不适宜晾晒。
旅游指数:一般,风稍大,较强降雨将给出行带来不便。
路况指数:湿滑,路面湿滑,车辆易打滑,减慢车速。
舒适度指数:舒适,白天不冷不热,风力不大。
空气污染指数:良,气象条件有利于空气污染物扩散。
紫外线指数:最弱,辐射弱,涂擦SPF8-12防晒护肤品。
9℃/23℃
10月2日 晴
北风3-4级转无持续风向微风
0.gif
0.gif
12℃/23℃
10月3日 晴
无持续风向微风
0.gif
0.gif
北京位于华北平原西北边缘,市中心位于北纬39度,东经116度xxx...
2 调用客户端
命令行生成客户端:
D:\asix2\axis2-1.6.2-bin\axis2-1.6.2\bin>wsdl2java.bat -uri http://www.web
xml.com.cn/WebServices/WeatherWebService.wsdl -p com.thrillerzw.springtest.axis2.client.stub -o f:\1
-p 为包名,-o 为输出目录
输出:
WeatherWebServiceCallbackHandler.java WeatherWebServiceStub.java
编写调用helper类:
package com.thrillerzw.springtest.axis2.client.stub; import java.rmi.RemoteException; import org.apache.axis2.AxisFault; import com.thrillerzw.springtest.axis2.client.stub.WeatherWebServiceStub.ArrayOfString; import com.thrillerzw.springtest.axis2.client.stub.WeatherWebServiceStub.GetWeatherbyCityName; import com.thrillerzw.springtest.axis2.client.stub.WeatherWebServiceStub.GetWeatherbyCityNameResponse; /** * 命令行生成axis2的客户端,获取北京的天气 * * @author thrillerzw * @date 2013年10月5日 */ public class WeatherWSHelper { public static void main(String[] args) { try { WeatherWebServiceStub stub = new WeatherWebServiceStub(); GetWeatherbyCityName request = new GetWeatherbyCityName(); request.setTheCityName("北京"); GetWeatherbyCityNameResponse response = stub .getWeatherbyCityName(request); ArrayOfString arr = response.getGetWeatherbyCityNameResult(); String[] strArr = arr.getString(); for (int i = 0; i < strArr.length; i++) { System.out.println(strArr[i]); } } catch (AxisFault e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
输出同第一种方式:
直辖市
北京
54511
54511.jpg
2013-10-5 21:50:35
12℃/22℃
。。。