软件需求
J2EE 7 SDK
Eclipse
Tomcat
Maven
JAX-WS的构成
SEI,全称Service Endpoint Interface或Service Endpoint Implemention。是服务器端和客户端开发真正要接触的类。
JAX-WS RI,全称JAX-WS Reference Implementation。这是JAX-WS的实现。与之相对立的应该是JAX-WS和JAXB API。
JAXB,全称Java Architecture for XML Binding。这是将Java类和XML schema相互映射的标准,此标准可以将Java实例转为XML,也可以将XML转为Java实例。
SAAJ,全称SOAP with Attachment API for Java。这是用于解析和生成SOAP协议数据的类库。
SEI中的方法中的参数,是由JAXB从SOAP中的XML数据转变而来,方法返回值,则由JAXB转为XML数据,然后通过SAAJ封装在SOAP消息中传回。所以,SEI中的方法参数和返回值,必须符合JAVA和XML Type的对应关系。
这里有一张映射表?http://docs.oracle.com/javaee/7/tutorial/doc/jaxws002.htm?
用图表示,JAX-WS的工作原理就是

SEI成功工作所依赖的自定义java类,都可以使用JEE SDK所提供的工具,自动产生。
开发流程
一般存在两种开发流程,从开发SEI开始,另一种是从开发WSDL开始。
从SEI开始
这种方式适合Java程序猿。
首先开发SEI。
-
使用JEE SDK中的工具wsgen,生成运行所依赖的所有Java类,class以及WSDL,XSD。
例如:wsgen -wsdl -r resource -s src -d stock -cp myclasspath stock.StockService
-wsdl 表示产生wsdl xsd文件
-r 表示wsdl产生在那个目录
-s 表示source放在哪个目录
-d 表示生成的最终文件放在哪个目录
编写配置文件
打包成WAR并发布。
从WSDL开始
这种方式适合跨平台
开发,或者从其它平台获取WSDL文件。
-
使用JEE SDK中的工具wsimport,生成SEI接口以及所有Java文件。
例如:?wsimport -p stockquote http://stockquote.xyz/quote?wsdl
为SEI接口编写SEI实现类。
打包并发布。
Maven
JAX-WS提供了Maven plugin,可以使用Maven简化上面的流程。详细过程请看后面的实例。
开发实例
下面我将一步一步的开发一个实例。
图书馆管理系统
创建Maven项目
在eclipse中,创建一个webApp的maven项目。JAXWS的Maven Plugin使用方法,可以在https://jax-ws-commons.java.net/jaxws-maven-plugin/?找到。Plugin中包含了最重要的两个goal,wsimport和wsgen。
由于JRE的lib中已经包含了JAXWS的所有包,但其版本可能不是你想要的。所以,在开发开发部署JAXWS的时候,存在着两种依赖方式:
使用JDK中自带的JAXWS版本。
使用其它版本。这需要Java Endorsed Standards Override Mechanism?.
本实验对JAXWS的版本要求不高,所以使用JDK自带的即可。
修改pom.xml,引入plugin。请加入以下代码:
<build>
????<pluginManagement>
????????<plugins>
????????????<plugin>
????????????????<groupId>org.eclipse.m2e</groupId>
????????????????<artifactId>lifecycle-mapping</artifactId>
????????????????<version>1.0.0</version>
????????????????<configuration>
????????????????????<lifecycleMappingMetadata>
????????????????????????<pluginExecutions>
????????????????????????????<pluginExecution>
????????????????????????????????<pluginExecutionFilter>
????????????????????????????????????<groupId>org.jvnet.jax-ws-commons</groupId>
????????????????????????????????????<artifactId>jaxws-maven-plugin</artifactId>
????????????????????????????????????<versionRange>[1.0,)</versionRange>
????????????????????????????????????<goals>
????????????????????????????????????????<goal>wsgen</goal>
????????????????????????????????????</goals>
????????????????????????????????</pluginExecutionFilter>
????????????????????????????????<action>
????????????????????????????????????<execute?/>
????????????????????????????????</action>
????????????????????????????</pluginExecution>
????????????????????????</pluginExecutions>
????????????????????</lifecycleMappingMetadata>
????????????????</configuration>
????????????</plugin>
????????</plugins>
????</pluginManagement>
????<plugins>
??????<plugin>
????????<groupId>org.jvnet.jax-ws-commons</groupId>
????????<artifactId>jaxws-maven-plugin</artifactId>
????????<version>2.3</version>
????????<executions>
??????????<execution>
????????????<id>wsgen-from-jdk</id>
????????????<phase>process-classes</phase>
????????????<goals>
??????????????<goal>wsgen</goal>
????????????</goals>
????????????<configuration>
??????????????<executable>${tool.wsgen}</executable>
??????????????<sei>com.mycompany.Library</sei>
??????????????<genWsdl>true</genWsdl>
????????????</configuration>
??????????</execution>
????????</executions>
??????</plugin>
????</plugins>
??</build>
??
??<!--?setup?corresponding?executables?on?win?-->
??<profiles>
????<profile>
??????<id>win</id>
??????<activation>
????????<os>
??????????<family>windows</family>
????????</os>
??????</activation>
??????<properties>
????????<tool.wsgen>D:/sts/jdk1.7.0_10/bin/wsgen.exe</tool.wsgen>
????????<tool.wsimport>D:/sts/jdk1.7.0_10/bin/wsimport.exe</tool.wsimport>
??????</properties>
????</profile>
??</profiles>
以上POM中的代码,将wsgen goal挂到process-classes phase上。其中PluginManagement部分是专门为eclipse m2e写的,因为execution无法在m2e中被cover。如果是独立maven环境,则不需要写PluginManagement.
创建完Maven项目以后,接下来,我们就可以创建WebService SEI了。
编写SEI
Library.java
package?com.mycompany;
import?java.util.ArrayList;
import?java.util.List;
import?javax.jws.WebMethod;
import?javax.jws.WebParam;
import?javax.jws.WebResult;
import?javax.jws.WebService;
@WebService(targetNamespace="http://library.mycompany.com")
public?class?Library?{
????private?static?List<Book>?bookList?=?new?ArrayList<Book>();
????private?static?int?currentId?=?0;
????
????public?Library()?{
????}
????@WebMethod
????@WebResult(name="id")
????public?int?addRawBook(@WebParam(name="name")?String?name,?@WebParam(name="author")?String?author)?{
????????Book?book?=?new?Book();
????????book.setId(++currentId);
????????book.setName(name);
????????book.setAuthor(author);
????????bookList.add(book);
????????return?currentId;
????}
????
????@WebMethod
????@WebResult(name="rawBook")
????public?String?getRawBook(@WebParam(name="id")?int?id)?{
????????Book?goal=null;
????????for(Book?b:?bookList)?{
????????????if?(id?==?b.getId())?{
????????????????goal?=?b;?
????????????????break;
????????????}
????????}
????????StringBuilder?result?=?new?StringBuilder();
????????if?(goal?==?null)?{
????????????result.append("No?Book?Found");
????????}?else?{
????????????result.append("[id=").append(goal.getId()).append(";name=").append(goal.getName()).append(";author=").append(goal.getAuthor());
????????}
????????return?result.toString();
????}
????
????@WebMethod
????public?void?deleteBook(@WebParam(name="id")?int?id)?throws?LibraryException?{
????????Book?goal=null;
????????for(Book?b:?bookList)?{
????????????if?(id?==?b.getId())?{
????????????????goal?=?b;?
????????????????break;
????????????}
????????}
????????if(goal?==?null)?{
????????????throw?new?LibraryException("Fail?to?delete",?"Id?not?exist.");
????????}?else?{
????????????bookList.remove(goal);
????????}
????}
}
另外还有Book和Exception的实现:
Book.java
package?com.mycompany;
public?class?Book?{
????public?int?getId()?{
????????return?id;
????}
????public?void?setId(int?id)?{
????????this.id?=?id;
????}
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????public?String?getAuthor()?{
????????return?author;
????}
????public?void?setAuthor(String?author)?{
????????this.author?=?author;
????}
????private?int?id;
????private?String?name;
????private?String?author;
}
LibraryException.java
package?com.mycompany;
public?class?LibraryException?extends?Exception?{
????private?String?detail;
????
????public?LibraryException(String?message,?String?detail)?{
????????super(message);
????????this.detail=detail;
????}
????
????public?String?getDetail()?{
????????return?detail;
????}
}
web.xml
在servlet3.0容器中,并不需要web.xml,请忽略下面。如果部署在2.5中,则需要声明webservice的servlet。
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>Library</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Library</servlet-name>
<url-pattern>/service</url-pattern>
</servlet-mapping>
sun-jaxws.xml
如果是glassfish,则不需要sun-jaxws.xml,自从java跟了oracle,oracle对java的各种规范极力支持,glassfish就是一个极度遵循j2ee规范的server。如果部署在tomcat及其它server上,则需要在WEB-INF下面创建sun-jaxws.xml.
<?xml?version="1.0"?encoding="UTF-8"?>
<endpoints?xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'?version='2.0'>
????<endpoint
????????name='Library'
????????implementation='com.mycompany.Library'
????????url-pattern='/service'/>
</endpoints>
部署
运行maven package命令,将得到的library.war复制到tomcat的目录下。访问页面http://127.0.0.1:8080/library/service?wsdl?
客户端
Maven Project
创建一个Maven project。在pom.xml中加入wsimport的命令。跟上面pom.xml一样,我只写出不一样的地方:
??????<plugin>
????????<groupId>org.jvnet.jax-ws-commons</groupId>
????????<artifactId>jaxws-maven-plugin</artifactId>
????????<version>2.3</version>
????????<executions>
??????????<execution>
????????????<id>wsimport-from-jdk</id>
????????????<goals>
??????????????<goal>wsimport</goal>
????????????</goals>
????????????<configuration>
??????????????<executable>${tool.wsimport}</executable>
??????????????<wsdlUrls>
????????????????<wsdlUrl>http://127.0.0.1:8080/library/service?wsdl</wsdlUrl>
??????????????</wsdlUrls>
????????????</configuration>
??????????</execution>
????????</executions>
??????</plugin>
在eclipse中,运行命令maven jaxws:wsimport,然后在target下面找到产生的java文件。将这些文件导入到src/main/java中。
写客户端
public?class?App?{
????public?static?void?main(?String[]?args?)?throws?LibraryException_Exception?{
????????int?id;
????????String?rawBook;
????????id?=?createPort().addRawBook("java",?"Tom");
????????System.out.println("Add?id="+id);
????????id=createPort().addRawBook("C",?"Sam");
????????System.out.println("Add?id="+id);
????????rawBook?=?createPort().getRawBook(2);
????????System.out.println("find"+rawBook);
????????createPort().deleteBook(2);
????????rawBook?=?createPort().getRawBook(2);
????????System.out.println("find"+rawBook);
????????createPort().deleteBook(2);
????}
????
????public?static?Library?createPort()?{
????????Library?port?=?new?LibraryService().getLibraryPort();
????????return?port;
????}
}
官方网址
https://jax-ws.java.net?