WebService第一天——概述与入门操作
一、概述
1.是什么
Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。[1]
Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
// 来自百度百科
提供webService的参考网址:http://www.webxml.com.cn/zh_cn/web_services.aspx
主要作用是使不同软件系统之间实现互联互通!
2.必会基础知识
名词1:XML. Extensible Markup Language -扩展性标记语言
XML,用于传输格式化的数据,是Web服务的基础。
namespace-命名空间。
xmlns=“http://itcast.cn” 使用默认命名空间。
xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
名词2:WSDL – WebService Description Language – Web服务描述语言。
通过XML形式说明服务在什么地方-地址。
通过XML形式说明服务提供什么样的方法 – 如何调用。
重点掌握的关系图:——拿到一个WSDL读取方式是从后往前读
名词3:SOAP-Simple Object Access Protocol(简单对象访问协议)
SOAP作为一个基于XML语言的协议用于有网上传输数据。
SOAP = 在HTTP的基础上+XML数据。
SOAP是基于HTTP的。
SOAP的组成如下:
Envelope – 必须的部分。以XML的根元素出现。
Headers – 可选的。
Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。
其中,WSDL的教程(以及SOAP教程)可以参考:菜鸟教程
二、基本入门操作
1.生成客户端代码
使用的是JDK1.6+的wsimport命令,其中两个参数的含义是:
-d<目录> - 将生成.class文件。默认参数。
-s<目录> - 将生成.java文件和class文件。
-p<生成的新包名> -将生成的类,放于指定的包下。
示例:
// 1表示当前目录,2表示WSDL的地址(当然不限于网络地址,可以另存为.wsdl的本地文件,然后使用本地路径D:/...)
2.webService客户端调用
步骤如下:
调用webservice步骤 1)打开WSDL文档 2)从下往上读WSDL文档,先找到Services(服务访问点集合),根据Services里面binding属性找到binding元素,再根据binding元素的type属性找到绑定的portType(服务类) 3)根据WSDL的地址生成客户端代码wsimport -s . -p com.rl.trans d:/wsCode/EnglishChinese.wsdl 4)把客户端代码拷贝到项目中 5)创建服务访问点集合对象 6)根据服务访问点获得服务类 7)调用服务类的方法
示例:
先把上面生成的代码复制到工程
再在工程中建立测试的类:
public static void main(String[] args) {
// 创建服务访问点集合
MobileCodeWS mc = new MobileCodeWS();
// 根据服务访问点获得绑定的类
MobileCodeWSSoap serviceClass = mc.getMobileCodeWSSoap();
// 调用具体业务逻辑
String info = serviceClass.getMobileCodeInfo("13407966980", null);
System.out.println("info = " + info);
}
结果:
另外一个含有mp3(字节流)的示例如下:
public static void main(String[] args) throws Exception { //创建服务访问点集合 EnglishChinese ec = new EnglishChinese(); //获得服务类 EnglishChineseSoap serviceClass = ec.getEnglishChineseSoap(); //调用服务方法 ArrayOfString aos = serviceClass.translatorString("hello"); List<String> strList = aos.getString(); for(String result : strList){ System.out.println(result); } //调用服务方法 byte[] mp3 = serviceClass.getMp3("1059.mp3"); OutputStream out = new FileOutputStream(new File("d:/wsCode/hello.mp3")); out.write(mp3); out.flush(); out.close(); }
3.使用jdk发布webService服务的发布
步骤如下:
a)@WebService - 它是一个注解,用在类上指定将此类发布成一个webservice服务. b)Endpoint – 此类为端点服务类,它的方法publish用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上。Endpoint是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。 static Endpoint.publish(String address, Object implementor) 在给定地址处针对指定的实现者对象创建并发布端点。stop方法用于停止服务。 其他注意事项: 1)给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。不支持静态方法,final方法。 2)如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。 3)如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。 4)服务类中不能没有方法 5)@WebMethod(exclude=true)屏蔽方法
示例:
服务类:
@WebService public class HelloServer { public String sayHello(String name) { return "hello "+name+" welcome to webService Server"; } }
发布服务:
public class ServerPublish {
public static void main(String[] args) {
// 使用JDK发布ws服务,包含发布地址与服务类的两个参数
Endpoint.publish("http://127.0.0.1:8080/hello", new HelloServer());
}
}
结果:请注意访问地址!
//可以使用第二点客户端的调用进行测试
4.其它调用webService的方式
使用原生AJAX调用:
var xhr; function invoke(){ if(window.ActiveXObject){ xhr = new ActiveXObject("Microsoft.XMLHTTP"); }else{ xhr = new XMLHttpRequest(); } //指定请求地址 var url = "http://127.0.0.1:7777/hello?wsdl"; //定义请求类型和地址和异步 xhr.open("POST", url, true); //设置Content-Type xhr.setRequestHeader("Content-Type", "text/xml;charset=UTF-8"); //指定回调方法 xhr.onreadystatechange = back; var textVal = document.getElementById("mytext").value; //组装消息体的数据 var data = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://server.hm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +'<soapenv:Body>' +'<q0:sayHello>' +'<arg0>'+textVal+'</arg0>' +'</q0:sayHello>' +'</soapenv:Body>' +'</soapenv:Envelope>'; xhr.send(data); } function back(){ if(xhr.readyState == 4){ if(xhr.status == 200){ var doc = xhr.responseXML; alert(doc); alert(xhr.responseText); var tag = doc.getElementsByTagName("return")[0]; alert(tag) } }
使用JQuery封装的AJAX调用:http://www.cnblogs.com/2013likong/p/3472144.html
使用URLConnection调用
//创建url地址 URL url = new URL("http://192.168.1.104:8080/hello"); //打开连接 URLConnection conn = url.openConnection(); //转换成HttpURL HttpURLConnection httpConn = (HttpURLConnection) conn; //打开输入输出的开关 httpConn.setDoInput(true); httpConn.setDoOutput(true); //设置请求方式 httpConn.setRequestMethod("POST"); //设置请求的头信息 httpConn.setRequestProperty("Content-type", "text/xml;charset=UTF-8"); //拼接请求消息 String data = "<soapenv:Envelope xmlns:soapenv=" + "\"http://schemas.xmlsoap.org/soap/envelope/\" " + "xmlns:q0=\"http://server.rl.com/\" " + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +"<soapenv:Body>" +"<q0:sayHello>" +"<arg0>renliang</arg0> " +"</q0:sayHello>" +"</soapenv:Body>" +"</soapenv:Envelope>"; //获得输出流 OutputStream out = httpConn.getOutputStream(); //发送数据 out.write(data.getBytes()); //判断请求成功 if(httpConn.getResponseCode() == 200){ //获得输入流 InputStream in = httpConn.getInputStream(); //使用输入流的缓冲区 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuffer sb = new StringBuffer(); String line = null; //读取输入流 while((line = reader.readLine()) != null){ sb.append(line); } //创建sax的读取器 SAXReader saxReader = new SAXReader(); //创建文档对象 Document doc = saxReader.read(new StringReader(sb.toString())); //获得请求响应return元素 List<Element> eles = doc.selectNodes("//return"); for(Element ele : eles){ System.out.println(ele.getText()); }
5.复杂数据类型传输
@WebService
public class TestComplexServer {
List<Person> pList = new ArrayList<Person>();
public void addPerson(Person person){
pList.add(person);
}
public List<Person> getPersonList(){
return pList;
}
public static void main(String[] args) {
Endpoint.publish("http://192.168.1.104:8888/person", new TestComplexServer());
}
}
测试代码:
public static void main(String[] args) { //创建服务访问点集合 PersonServerService pss = new PersonServerService(); //根据服务访问点获得绑定的类 PersonServer server = pss.getPersonServerPort(); //调用具体业务逻辑 Person person = new Person(); person.setId(1); person.setName("zhaoliu"); person.setAge(20); person.setAddress("xiangyashan"); Person person1 = new Person(); person1.setId(2); person1.setName("tianqi"); person1.setAge(25); person1.setAddress("gaolaozhang"); //调用添加人的webservice服务方法 /*server.addPerson(person); server.addPerson(person1);*/ //调用查询所有人的webservice服务方法 List<Person> pList = server.getPersonAll(); for(Person p : pList){ System.out.println("id: "+p.getId()+" name:"+p.getName() + " age:"+p.getAge() + " address:"+p.getAddress()); } }
7.修改WSDL文档
WSDL文档并非一经发布便不可更改,可供修改项如下:
自动生成的文档的名字有时不规范,可以手动进行修改。
@WebService(
portName="myHelloService",修改端口名字
serviceName="HelloServices",修改服务访问点集合名字
name="HelloService",修改服务类的名字
targetNamespace="hello.rl.com" 修改命名空间名字
)
@WebResult(name="sirHello")修改返回值的元素的父标签名字——在方法返回值前加注解修改
@WebParam(name="sir")修改传入参数的元素的父标签名字——在方法参数前加注解修改
webService参考教程:http://www.cnblogs.com/yangang2013/p/5708647.html