软件需求
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;
}
}
官方网址
来源:oschina
链接:https://my.oschina.net/u/254689/blog/224912