什么是weebservice?
web service 即是web服务,它是一种跨越编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术。
采用标准SOAP(Simple Object AccessProtocol) 协议传输,soap属于w3c标准。Soap协议是基于http的应用层协议,soap协议传输是xml数据。
采用wsdl作为描述语言即webservice使用说明书,wsdl属w3c标准。
xml是webservice的跨平台的基础,XML主要的优点在于它既与平台无关,又与厂商无关。
XSD,W3C为webservice制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的webservice接口在发送数据时都要转换成webservice标准的XSD发送。
当前非SOAP协议的webService以轻量为首要目标,比如http rest方式也是webservice的一种方式,或者直接使用http自定义数据协议,比如http传输json数据,http传输xml数据等。
WebService的三要素:
SOAP:
简单对象访问协议(Simple Object Access Protocal )是一种简单的基于XML的协议,他使应用程序通过HTTP来交换信息,简单理解为soap=http+xml。soap协议版本主要使用soap1.1和soap1.2.SOAP不是webservice的专有协议,其他应用协议也使用soap传输数据。例如,SMTP、tr069等。
wsdl:
wsDL:是基于XML的用于描述webservice及其函数、参数和返回值。通俗理解为wsdl是webservice的使用说明书。
UUDI:
是一种目录服务,通过它,企业可注册并搜索 Web services。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册的web service服务,从而达到资源共享。 UDDI旨在将全球的webservcie资源进行共享,促进全球经济合作。
webservice开发规范:
JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
JAX-WS: Java API for XML-BasedWebservices 。早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(Java API For XML-Remote Procedure Call)目前已经被JAX-WS 规范取代。
JAX&SAAJ:JAVA API FOR XML Message。SAAJ(SOAP With Attachment APIFor Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输等,JAXM&SAAJ 与JAX-WS 都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ 暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节
JAX-RS:JAX-RS 是JAVA 针对REST(Representation State Transfer)风格制定的一套Web 服务规范,由于推出的较晚,该规范(JSR 311,目前JAX-RS 的版本为1.0)并未随JDK1.6 一起发行。
目前使用较多的是jax-ws和jax-rs.jax-rs推出的时间不久,所以一般大公司用的比较多,jax-ws小公司用的多。
客户-服务器模式:
webService四种客户端调用方式
客户端服务器模式:
1.:服务器端开发:
编写SEI(Service Endpoint Interface),SEI在webService中称为portType,在java中成为接口。
public interface WeatherInterface {
//天气查询
public String queryWeather(String cityName);
}
2.编写SEI实现类并发布,此类为webService提供服务类
@WebService
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client.."+cityName);
String result = "晴朗";
System.out.println("to client..."+result);
return result;
}
public static void main(String[] args) {
//发送webservice服务
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
}
}
注意:SEI实现类中至少要有一个非静态的公共方法需要作为webservice服务的方法,。public class上边要加上@webservice
查看wsdl:
1. 在地址栏输入(注意后面的参数?wsdl)
http://192.168.1.100:1234/weather?wsdl
2. Wsdl不是webService,只是获取一个用于描述WebService的说明文件
3. wsdl- WebServiceDescriptionLanguage,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务.
Wsimport生成客户端调用类:wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码,服务端通过客户端代码调用webservice。
wsimport.exe位于JAVA_HOME\bin目录下.
常用参数为:
-d<目录> - 将生成.class文件。默认参数。
-s<目录> - 将生成.java文件。
-p<生成的新包名> -将生成的类,放于指定的包下。
(wsdlurl) - http://server:port/service?wsdl,必须的参数。
示例:
C:/> wsimport –s .http://127.0.0.1:1234/weather?wsdl
注意:-s不能分开,-s后面有个小点
客户端编写(Wsimport实现):public class WeatherClient {
public static void main(String[] args) {
//创建服务视图
WeatherInterfaceImplService weatherInterfaceImplService =new WeatherInterfaceImplService();
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl= weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class);
//调用webservice服务方法
String result = weatherInterfaceImpl.queryWeather("郑州");
System.out.println(result);
}
}
service方式
客户端编写(service实现):
/**
* 使用javax.xml.ws.Service调用webservice服务
* @author 传智播客 Java学院
* @version V1.0
*/
public class WeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定义url,参数为wsdl地址
URL url = new URL("http://192.168.1.100:1234/weather?wsdl");
//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
QName qName = new QName("http://impl.sei.jaxws.ws.itcast.cn/", "WeatherInterfaceImplService");
//创建服务视图
Service service = Service.create(url, qName);
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//调用webservice
System.out.println(weatherInterfaceImpl.queryWeather("郑州"));
}
}
使用service调用和wsimport代码调用方式区别:
Wsimport生成代码调用webservice无法指定webservice的地址,使用生成的服务视图类获取服务端点(postType)实例。
Service调用Webservice可以指定webservice的地址,只需要服务端点的接口即可获取服务端点实例。
webservice优点:1、采用xml支持跨平台远程调用。
2、基于http的soap协议,可跨越防火墙。
3、支持面向对象开发。
4、有利于软件和数据重用,实现松耦合。
webservice缺点:由于soap是基于xml传输,本身使用xml传输会传输一些无关的东西从而效率不高,随着soap协议的完善,soap协议增加了许多内容,这样就导致了使用soap协议进行数据传输的效率不高。
webService的应用场景:宏观:用于软件集成和复用
微观:用于接口服务:不考虑客户端类型,不考虑性能,建议使用
用于公开接口服务:面向互联网公开的接口,比如火车时刻查询接口等等。
用于内部接口服务:一个大的系统是由若干个系统组成的,系统与系统之间存在数据访问需求,为了减少系统与系统之间的耦合性可以将接口抽取出来单独的接口服务供给其他系统调用。
适用:
用于接口,不考虑客户端类型,不考虑性能,建议使用
服务端已经确定使用webservice,客户端无法选择,只能使用webservice
不适用:
对性能要求很高的应用,不建议使用webservice
比如银行交易系统、股票交易系统等,任何延迟都可能造成无法估量的损失。
同构程序之间通信不建议使用webservice
比如Java的RMI同样可以实现远程调用,而且性能比webservice好很多。
soap是什么:
SOAP 是一种网络通信协议
SOAP即Simple Object Access Protocol简易对象访问协议
SOAP 用于跨平台应用程序之间的通信
SOAP 被设计用来通过因特网(http)进行通信
SOAP = HTTP+XML,其实就是通过HTTP发xml数据
SOAP 很简单并可扩展支持面向对象
SOAP 允许您跨越防火墙
SOAP 将被作为 W3C 标准来发展
使用TCP/IP Monitor监视soap协议使用TCP/IP Monitor可以监视tcp/ip协议的报文内容,由于http是基于Tcp的应用协议,而webservice是基于http实现,所以通过tcp/ipmonitor可以监视webservice请求及响应的内容。
客户端编码:
tcp/ip在eclipse的show view下边的other中输入tcp查找选择显示,然后通过下拉三角找到properties从而添加一个monitor
//定义url,参数为wsdl地址
URL url = new URL("http://127.0.0.1:54321/weather?wsdl");
//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
QName qName = new QName("http://server.jaxws.webservice.itcast.cn/", "WeatherInterfaceImplService");
//创建服务视图
Service service = Service.create(url, qName);
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//调用webservice
System.out.println(weatherInterfaceImpl.queryWeather("郑州"));
soap协议体重包含以下元素:
必需有 Envelope 元素,此元素将整个 XML 文档标识为一条 SOAP 消息
可选的 Header 元素,包含头部信息
必需有Body 元素,包含所有的调用和响应信息
可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
soap消息基本结构部:<?xmlversion="1.0"?>
<soap:Envelopexmlns: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>
http发送soap协议:
/**
* 通过http发送soap协议请求webservice
* @author 传智播客 Java学院
* @version V1.0
*/
public class HttpRequestSoap {
public static void main(String[] args) throws IOException {
//webservice地址
String webservice_url = "http://127.0.0.1:1234/weather";
//发送的soap协议内容
String soap_xml = soap_xml("郑州");
System.out.println(soap_xml);
//创建url
URL url = new URL(webservice_url);
//创建http链接对象
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
//设置请求方法
httpURLConnection.setRequestMethod("POST");
//设置Content-type
httpURLConnection.setRequestProperty("Content-type", "text/xml;charset=\"utf-8\"");
//使用http进行输出
httpURLConnection.setDoOutput(true);
//使用http进行输入
httpURLConnection.setDoInput(true);
//通过输出流发送数据
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(soap_xml.getBytes());
outputStream.close();
//接收服务端响应数据
InputStream inputStream = httpURLConnection.getInputStream();
//使用buffer存在读取的数据
byte[] buffer = new byte[1024];
//使用字节输出流存储读取的数据
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while(true){
int len = inputStream.read(buffer);
//如果流水读取完则退出循环
if(len == -1){
break;
}
byteArrayOutputStream.write(buffer,0,len);
}
//得到响应数据
String response_string = byteArrayOutputStream.toString();
System.out.println(response_string);
parseXml(response_string);
}
//soap协议内容
public static String soap_xml(String cityName){
String soap_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<S:Body>"
+ "<ns2:queryWeather xmlns:ns2=\"http://impl.sei.jaxws.ws.itcast.cn/\">"
+ "<arg0>"+ cityName + "</arg0>"
+ "</ns2:queryWeather>"
+ "</S:Body>"
+ "</S:Envelope>";
return soap_xml;
}
//解析响应的xml
public static String parseXml(String xmlString){
String result = null;
try {
Document document = DocumentHelper.parseText(xmlString);
//创建xpath解析对象
DefaultXPath defaultXPath = new DefaultXPath("//ns2:queryWeatherResponse");
//指定命名空间
defaultXPath.setNamespaceURIs(Collections.singletonMap("ns2", "http:// impl.sei.jaxws.ws.itcast.cn/"));
List<Element> elements= defaultXPath.selectNodes(document);
Element response = elements.get(0);
List<Element> results = response.selectNodes("return");
System.out.println(results.get(0).getText());
} catch (DocumentException e) {
e.printStackTrace();
}
return result;
}
}
ajax方式
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
function queryMobile(){
//创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//打开连接
xhr.open("post","http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx",true);
//设置数据类型
xhr.setRequestHeader("content-type","text/xml;charset=utf-8");
//设置回调函数
xhr.onreadystatechange=function(){
//判断是否发送成功和判断服务端是否响应成功
if(4 == xhr.readyState && 200 == xhr.status){
alert(xhr.responseText);
}
}
//组织SOAP协议数据
var soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+"<soap:Envelope 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/\">"
+"<soap:Body>"
+"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
+"<mobileCode>"+document.getElementById("phoneNum").value+"</mobileCode>"
+"<userID></userID>"
+"</getMobileCodeInfo>"
+"</soap:Body>"
+"</soap:Envelope>";
alert(soapXML);
//发送数据
xhr.send(soapXML);
}
</script>
</head>
<body>
手机号查询:<input type="text" id="phoneNum"/> <input type="button" value="查询" οnclick="javascript:queryMobile();"/>
</body>
</html>