JAX-WS开发WebService初级

软件需求

  1. J2EE 7 SDK

  2. Eclipse

  3. Tomcat

  4. Maven

JAX-WS的构成

  1. SEI,全称Service Endpoint Interface或Service Endpoint Implemention。是服务器端和客户端开发真正要接触的类。

  2. JAX-WS RI,全称JAX-WS Reference Implementation。这是JAX-WS的实现。与之相对立的应该是JAX-WS和JAXB API。

  3. JAXB,全称Java Architecture for XML Binding。这是将Java类和XML schema相互映射的标准,此标准可以将Java实例转为XML,也可以将XML转为Java实例。

  4. 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的工作原理就是

JAX-WS开发WebService初级_第1张图片

SEI成功工作所依赖的自定义java类,都可以使用JEE SDK所提供的工具,自动产生。

开发流程

一般存在两种开发流程,从开发SEI开始,另一种是从开发WSDL开始。

从SEI开始

这种方式适合Java程序猿。

  1. 首先开发SEI。

  2. 使用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 表示生成的最终文件放在哪个目录

  3. 编写配置文件

  4. 打包成WAR并发布。

从WSDL开始

这种方式适合跨平台

  1. 开发,或者从其它平台获取WSDL文件。

  2. 使用JEE SDK中的工具wsimport,生成SEI接口以及所有Java文件。

    例如: wsimport -p stockquote http://stockquote.xyz/quote?wsdl

  3. 为SEI接口编写SEI实现类。

  4. 打包并发布。

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的时候,存在着两种依赖方式:

  1. 使用JDK中自带的JAXWS版本。

  2. 使用其它版本。这需要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 

你可能感兴趣的:(webservice,jax-ws)