自定义WebService和客户端调用《二》

来源:互联网 发布:结婚路线图制作软件 编辑:程序博客网 时间:2024/04/27 13:42

问题?自定义WebService和客户端调用《二》,客户端调用有几种方式


一、JDK创建WebService服务和使用

Oracle前身sun公司,早就意识到WebService的强大,和它的未来前景,所以在JDK中早就封装了这样的创建WebService服务。

查看DJK-API文档:

               


1.新建Java或web工程,建一个类(这个类作为服务端):

<span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.ws;import javax.jws.WebService;import javax.xml.ws.Endpoint;@WebService  //表示这个类,代表的是启动服务,ServiceName名字可以改,默认不写的话,名字为类名加Servicepublic class HelloService {public String sayhello(String name){//能够访问的借口方法,必须是public方法System.out.println("Hello:  "+name);return "Hello:  "+name;}public String sayhello1(){return "成功调用第二个服务器方法";} public static void main(String[] args) { /*  * 调用静态的方法Endpoint.publish创建一个服务  * 1.address:URI,指定要使用的地址和传输/协议,也就是服务地址  * 2.implementor:实现者,也就是服务端  */ <pre name="code" class="java"><span style="white-space:pre"></span>//使用自建端口号之前,cmd中使用netstat -a 检查一下端口是否被占用</span></span>
Endpoint.publish("http://localhost:9090/hello", new HelloService());System.out.println("启动服务:new HelloService");}}

/**如果改成private方法的话就会出现以下错误,我们做这个webservcie服务就是为了,*公布数据给别人用的,给成私有的,就达不到目的了,自然就会出错。Static、finally也不行

*Exception in thread "main"com.sun.xml.internal.ws.model.RuntimeModelerException: The web *service definedby the class com.itcast.ws.HelloService does not contain any valid WebMethods.

*/

运行:

如果出现错:Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException:解决办法将jdk升级到1.7版本,MyEclispe的preference下java install(一般情况下,MyEclispe用的而是自身带的JDK,而不是安装得JDK,需要配置一下)

否则就运行成功:

       

或者网页调用:http://localhost:9090/hello或http://localhost:9090/hello?wsdl  看看wsdl服务描述文档

       

2.新建客户端,并且调用该服务,在调用过程中,该服务必须一直开启

用wsimport -s . http://localhost:9090/hello?wsdl来生成本地代码,在上一文章中已经说过怎么做了。

把生成的文件夹拷入到客户端项目src下,并且新建一个测试调用类:

<span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.test;import org.junit.Test;import com.itcast.ws.HelloService;import com.itcast.ws.HelloServiceService;public class test1 {@Testpublic void testService(){HelloServiceService helloServiceService = new HelloServiceService();HelloService service = helloServiceService.getHelloServicePort();String name = service.sayhello("李*****");System.out.println("成功获取数据包: "+name+" "+service.sayhello1());}}</span></span>

这里的HelloServiceService是来自访问网网址?wsdl文件中的,所以不需要去看wsdl文档。

说到这里了,我们就会忍不住提出,那么通过wsimport -s .生成的代码,导入到工程中,我怎么知道,调用哪个服务,调用哪个接口呢?就需要深入看看WebService的深入理解了。



二、深入了解WebService配置

1.注解声明类为@WebService,不然就会报错。
不然报这个错误:class cn.itcast.ws.HelloService has neither @WebService nor @WebServiceProvider annotation


必须有至少一个public方法,且这个方法不能是static,final
不然就hi报这个错误:cn.itcast.ws.HelloService does not contain any valid WebMethods.


/**如果改成private方法的话就会出现以下错误,我们做这个webservcie服务就是为了,*公布数据给别人用的,给成私有的,就达不到目的了,自然就会出错。Static、finally也不行
*Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException: The web *service defined by the class com.itcast.ws.HelloService does not contain any valid WebMethods.
*/


2.如何查看说明wsdl

前面提到,怎么知道调用哪个服务,怎么知道调用哪个接口,这里就会讲到了。

WSDL文档说明服务

端口

方法

参数


访问看看:http://localhost:9080/hello?xsd=1



返回值


3.MyEclipes提供WebService工具


它有两个作用:

1.第一个作用可以用来测试服务端的数据
2.第二个作用可以获取发出SAOP请求的代码,(它会返回WSDL代码,在AJAX市级开发中使用特别多)和返回SAOP结果的代码,在AJAX之中用得比较多。比如以下:


    

注意:这个工具有一个最不好的缺点,就是它不支持SAOP1.2,它只支持1.1版本。


三、Ajax调用WebService服务


响应的一样,首先WebService服务的搭建,有服务接口,与接口中的方法,开启服务。

然后用MyEclipes提供WebService工具获取到接口的SAOP请求的代码,如以上那张图片。


首先你得有AJAX的基础才能做这一块哈。

<span style="font-family:Microsoft YaHei;font-size:18px;"><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title><script type="text/javascript">/*思路:1.创建一个XMLHTTP对象2.打开链接open("POST",url)3.设置请求头Content-Type4.设置回调函数,处理返回值5.从返回的XML中解析我们要的内容*/var xmlHttpReqquest = new ActiveXObject("Microsoft.XMLHTTP");//alert(xmlHttpReqquest);//发送SOAP请求function sendMsg(){//获取用户输入的内容var name = document.getElementById("name").value;var url = "http://localhost:9080/hello";var requestBody = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://ws.itcast.cn/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"+ "<soapenv:Body><q0:sayHello><arg0>"+name+"</arg0></q0:sayHello></soapenv:Body></soapenv:Envelope>";xmlHttpReqquest.open("POST", url);xmlHttpReqquest.setRequestHeader("Content-Type","text/xml;charset=utf-8");xmlHttpReqquest.onreadystatechange = _back;xmlHttpReqquest.send(requestBody);}//接收SOAP返回,从返回XML中解析function _back(){//处理完毕,处理成功if(xmlHttpReqquest.readystate==4){//处理完if(xmlHttpReqquest.status==200){//成功var xml = xmlHttpReqquest.responseXML;//alert(xml);//获取return标签的第一个var ele = xml.getElementsByTagName("return")[0];alert(ele.text);}}}</script></head><body><input type="text" id="name" name="name" value=""/><input type="button" name="send" value="send" onclick="sendMsg();"/></body></html></span>

启动tomcate或者其他服务器,测试一下是否调用得了。


四、HttpURLConnection方式调用WebService服务

同样的这种方式,也需要SAOP请求的消息。同样用MyEclispe工具获取


如:

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.test;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import org.junit.Test;public class RequestUrlConnectionTest {@Testpublic void uriTest() throws IOException{/* *1.创建一个url *2.打开一个连接 *3.设置相关参数 *4.创建输出流,用来发送SAOP请求 *5.发送完,接收数据 *6.用输入流获取webservice中的内容 */URL url = new URL("http://localhost:9090/hello");HttpURLConnection connection = (HttpURLConnection)url.openConnection();connection.setRequestMethod("POST");//必须设置为POST方式,而且必须是大写的connection.setDoInput(true);//因为有输入参数也有输出参数所以都为真connection.setDoOutput(true);connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8");OutputStream out = connection.getOutputStream();String argo="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://ws.itcast.cn/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"+"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><q0:sayhello><arg0>jack</arg0></q0:sayhello></soapenv:Body></soapenv:Envelope>";out.write(argo.getBytes());//发送SAOP请求InputStream stream = connection.getInputStream();byte[] b = new byte[1024];int len=0;StringBuffer buffer = new StringBuffer();while((len=stream.read(b))!=-1){String s = new String(b, 0, len, "utf-8");buffer.append(s);}System.out.println(buffer.toString());}}</span>

五、QName调用WebService方式

这个QName的链接地址要WSDL说明书


           

用cmd打包好的本地调用代码,复制到客户端项目中,只留下服务接口(那个是服务的接口,参照说明书),其他都删掉,里面的错的可以删掉

                    


<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.test;import java.net.MalformedURLException;import java.net.URL;import javax.xml.namespace.QName;import javax.xml.ws.Service;import org.junit.Test;import com.itcast.ws.HelloService;public class QnameTest {/* * 1.创建service对象,service.create(wsdlDocumentLocation, serviceName) * wsdlDocumentLocation:URL服务地址,而且需要wsmdl描述 * serviceName:Qname,这就是用这个方式的核心,因为他只用到service接口 * Qname:需要两个参数,一个是打包的空间,另外一个是这个服务名称(描述文件中的的服务名) *  * 2.通过service对象调用接口 * 3.通过接口对象来调用服务端方法 */@Testpublic void qnametest1() throws MalformedURLException{URL url = new URL("http://localhost:9090/hello?wsdl");QName serviceName = new QName("http://ws.itcast.com/", "HelloServiceService");Service service = Service.create(url, serviceName );HelloService helloService = service.getPort(HelloService.class);String name = helloService.sayhello("Mr_Li");String naem1 = helloService.sayhello1();System.out.println("调用service成功:"+name+"\n"+naem1);}}</span>


六、注解开发

前面我用的调用接口服务,需要知道说明书上写明那个服务,然后我们才去写,因为那些服务名称都是它自动加上的基本结构为:服务名+Service,还有命名空间是跟建得包是烦着过来的。如果采取注解的形式去开发,那么就不需要知道服务名称(针对于程序猿)。


@WebService

@WebService(serviceName="MyService")
修改产生的服务的名称
@WebService(serviceName="MyService",targetNamespace="http://cn.itcast.ws/")

修改命名空间
@WebMethod(operationName="hello")
修改方法名称
@WebParam(name="name")
修改参数名称
@WebResult(name="returnMsg")
修改返回名称
@WebMethod(exclude=true)
将指定的public方法排除,用户不能访问

如:

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.ws;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.ws.Endpoint;@WebService(serviceName="MyService",targetNamespace="http://com.itcast.ws/")  //表示这个类,代表的是启动服务,ServiceName名字可以改,默认不写的话,名字为类名加Servicepublic class HelloService {@WebMethod(operationName="Hello1")@WebResult(name="returnResult")public String sayhello(@WebParam(name="name")String name){System.out.println("Hello:  "+name);return "Hello:  "+name;}@WebMethod(operationName="Hello2",exclude=true)public String sayhello1(){return "成功调用第二个服务器方法";} public static void main(String[] args) { /*  * 调用静态的方法Endpoint.publish创建一个服务  * 1.address:URI,指定要使用的地址和传输/协议,也就是服务地址  * 2.implementor:实现者,也就是服务端  */Endpoint.publish("http://localhost:9090/hello", new HelloService());System.out.println("启动服务:new HelloService");}}</span>


执行命令看看是不是这样的:

http://localhost:9090/hello?wsdl
http://localhost:9090/hello?xsd=1


七、监控工具TCP/IP监控


有时候我们需要监听整个webservice的调用状态,需要用到MyEclipse的一个监听工具(只有高版本才有这个工具)

         

采用的是TCP/IP的方式来监听的。需要监听的端口号和被监听的端口号不同。


八、总结

1.UDDI/WSDL/SOAP的概念

2.wsimport –s . http::///// 生产本地调用代码


3.注意:支持soap1.0协议


4.发布服务 Endpoint.publish静态方法
参数1访问地址,参数2实现类。


5.Service类,它有静态方法create可以创建一个Web服务

6.调用方式:
A. 客户端的方式
B. MyEclipse自带工具WebService Expolor 帮助测试,直接获取到发送和接收的SOAPxml
C. Ajax ,不需生成本地调用代码,可以直接访问,在实际项目中使用比较多
D. HttpURLConnection对象,是以流方式
E. QName方式,内部使用方式,实际开发中常采用实际开发中可以选择其中一种




7.对象封装
业务比较复杂,按原有的方式写po类,按原有的方式写Service层,在Server服务端调用业务层service。实现业务逻辑。

总结:还没完呢,请看下一篇文章点击打开文章链接

2 0