准备工作
下载最新版本的JAX-WS RI(此处为2.2.8):
http://repo.maven.apache.org/maven2/com/sun/xml/ws/jaxws-ri/2.2.8/jaxws-ri-2.2.8.zip
解压后如下图所示:
- bin目录下是两个自动生成一些文件的工具,分别是wsgen.bat(对应linux环境的wsgen.sh)和wsimport.bat(对应linux环境的wsimport.sh)。wsgen命令主要用于Server端通过java类编译成WebService及相关的wsdl文件;wsimport则主要用于Client端(即调用端)通过wsdl文件编译出调用Server端的Java文件。
- doc目录下是JAX-WS的发布文档。包括一些发布日志和用户手册,还有wsgen和wsimport工具的使用法及一些常见问题等等。
- lib目录下包含Java工程所需的所有jar包,在后面开发时需要将这些jar包导入到工程中。
- samples目录下包含一些WebService的示例。
服务端的Hello WebService
开发环境:Spring Tool Suite
从现在开始,我们需要创建一个关于WebService的应用。
package com.ws; import javax.jws.WebMethod; import javax.jws.WebService; /** * WebService入门学习 * WebService注解是告诉JAXWS,这是一个WebService类 * * @author 14040875 * */ @WebService public class Hello { /** * 向接收的名字问好 * WebMethod注解告诉JAXWS,此方法为soap方法 * * @param name * @return */ @WebMethod public String say(String name){ return "Hello," + name; } }
至此,关于WebService所需要的类就编写完成了。接下来我们需要做一些配置和生成的工作。
首先编译Hello.java文件,得到对应的class文件。这个工作可以交给STS去做,我们只需要将工程部署到Web容器上,点击发布即可。打开工程部署的位置,就可以看到编译后的Hello.class文件,如下图:
记住这个路径,稍后就会用到:D:\dev\apache-tomcat-7.0.53\webapps\HelloWebService\WEB-INF\classes\com\ws
生成JAXWS相关文件
接着,之前提到的两个工具wsgen和wsimport需要加入到环境变量,以便于在命令行中使用它们。设置完成后,打开命令行窗口,输入wsgen命令,回车。
如果出现上图结果,说明这个命令是可用的;反之,则不可用。如果这个命令不能用,请检查是否正确设置了环境变量,将JAXWS RI的安装目录添加到环境变量即可。
wsgen -cp D:\dev\apache-tomcat-7.0.53\webapps\HelloWebService\WEB-INF\classes com.ws.Hello -wsdl -s wssrc -d build -r wsdl
其中:
- -wsdl 表示生成的是webservice
- -s 指出生成的.java文件放置位置
- -d 用于提示要生成的编译class文件在何处
- -r 表示生成.wsdl和xsd文件放于何处
- -cp 代表classpath,也就是Hello.class的位置
HelloService_schema1.xsd
HelloService.wsdl
<?xml version="1.0" encoding="UTF-8"?> <endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'> <endpoint name='Hello' implementation='com.ws.Hello' url-pattern='/HelloService' /> </endpoints>
OK,万事具备,再为已经存在WebService配置一下访问路径,同时把一直缺失的web.xml文件补上。
<?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> <span style="white-space:pre"> </span><servlet-name>Hello</servlet-name> <span style="white-space:pre"> </span><servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class> <span style="white-space:pre"> </span><load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <span style="white-space:pre"> </span><servlet-name>Hello</servlet-name> <span style="white-space:pre"> </span><url-pattern>/HelloService</url-pattern> </servlet-mapping> </web-app>
再次发布工程,在浏览器地址栏输入路径 http://127.0.0.1:8080/HelloWebService/HelloService?wsdl,就可以看到如下结果:
至此,WebService的服务端开发工作就完成了!
使用WebService接口
WebService接口有同步调用和异步调用来年高中方式,同步调用即为请求发出后,直到得到结果才继续执行后面的任务;异步调用则为,请求发出后,不等待返回结果,继续处理其它任务。一旦请求返回结果,再通知请求发送方。
然后打开命令行窗口,将工作目录切换到Java工程所在目录,输入如下命令:
wsimport -keep -d bin -s src wsdl/HelloService.wsdl
需要关注的是HelloService文件中,有两处路径需要改动,一处是这个类有一个注解@WebServiceClient,其中属性wsdlLocation的值修改为刚才服务端在浏览器中输入的地址,即:
http://127.0.0.1:8080/HelloWebService/HelloService?wsdl,另一处为这个类中一段static{}代码段里的url = new URL(...)也是修改为
http://127.0.0.1:8080/HelloWebService/HelloService?wsdl。
现在,我们可以创建一个HelloClient类,来使用我们的WebService接口:
package com.ws; public class HelloClient { public static void main(String[] args) { HelloService service = new HelloService(); Hello port = service.getHelloPort(); System.out.println(port.say("Mike")); } }
运行程序,就能到如下结果:
异步调用WebService
我们重新创建一个普通的Java工程(非必要,也可以在之前的Java工程中继续操作),并将wsdl文件和xsd文件放在工程的wsdl目录下。异步调用的命令要比同步调用稍微麻烦些,需要在工程的根目录下创建一个binging.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" wsdlLocation="wsdl/HelloService.wsdl" xmlns="http://java.sun.com/xml/ns/jaxws"> <bindings node="wsdl:deFinitions"> <enableAsyncMapping>true</enableAsyncMapping> </bindings> </bindings>
同时生产java类的命令也与同步的生成类的命令不同:
wsimport -keep –b binding.xml -d bin -s src wsdl/HelloService.wsdl
接着创建一个测试类,还叫HelloClient吧:
package com.ws; import javax.xml.ws.Response; public class HelloClient { public static void main(String[] args) throws Exception { HelloService service = new HelloService(); Hello port = service.getHelloPort(); Response<SayResponse> sayAsync = port.sayAsync("Mike"); while (!sayAsync.isDone()) { System.out.println("waiting..."); } try { SayResponse callNameResponse = sayAsync.get(); String message = callNameResponse.getReturn(); System.out.println(message); } catch (Exception ex) { } } }运行程序,得到如下结果:
package com.ws; import javax.xml.ws.AsyncHandler; import javax.xml.ws.Response; public class HelloClient { public static void main(String[] args) throws Exception { HelloService service = new HelloService(); Hello port = service.getHelloPort(); port.sayAsync("Mike",new AsyncHandler<SayResponse>() { public void handleResponse(Response<SayResponse> res) { try { SayResponse response = null; response = res.get(); String message = response.getReturn(); System.out.println(message); } catch (Exception e) { e.printstacktrace(); } System.out.println("Callback!"); } }); System.out.println("begin waiting..."); Thread.sleep(1000); } }
运行程序,得到如下结果: