目录

JAXWS

概述

JAX-WS = Java API For XML Web Service

JAX-WS规范定义了一组XML web services的Java API,它运行时实现会将这些API的调用转换成对应的soap消息,是Sun公司提出的一套关于WebService的开发标准。

JAXB

JAXB介绍

JAXB是Java Architecture for XML Binding的缩写,提供了一个快捷的方式将Java对象与XML进行转换,XML现在已经逐渐被JSON给替代。

在JAX-WS(Java的WebService规范之一)中,JDK1.6自带的版本JAX-WS2.1,其底层支持就是JAXB。

JAXB可以实现POJO对象与XML之间的相互转换

Unmarshaller类将XML数据反序列化为新创建的Java内容树的过程,并且可以在解组时有选择的验证XML数据。

Marshaller类将Java内容树序列化回XML数据的过程。

http://img.cana.space/picStore/20201109191506.png

示例

步骤

  1. 定义POJO类Book.java,使用注解@XmlRootElement标注在类上

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    package com.eh.webservice.demo;
       
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
       
    import javax.xml.bind.annotation.XmlRootElement;
       
    @XmlRootElement
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    public class Book {
        private long id;
        private String bookName;
        private double price;
    }
    
  2. 编写Marshaller工具类

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    package com.eh.webservice.demo;
       
    import lombok.SneakyThrows;
       
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    import java.io.OutputStream;
    import java.io.Reader;
       
    public class MarshallerUtil {
       
      // pojo -> xml
        @SneakyThrows
        public static <T> void marshal(T t, OutputStream os) {
            JAXBContext jaxbContext = JAXBContext.newInstance(t.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            // 用来指定是否对已编组XML数据的属性名称使用换行和缩排进行格式化
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            // 用来指定字符编码格式
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            // Java对象转换为XML格式,并且输出到指定输出流
            marshaller.marshal(t, os);
        }
       
      // xml -> pojo
        @SneakyThrows
        public static <T> T unmarshal(Reader reader, Class<T> clazz) {
            JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            T t = (T) unmarshaller.unmarshal(reader);
            return t;
        }
    }
    
  3. 测试

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    package com.eh.webservice.demo;
       
    import java.io.StringReader;
       
    public class MainTest {
        public static void main(String[] args) {
            Book book = new Book(100001L, "三国演义", 20.5);
            // pojo -> xml
            MarshallerUtil.marshal(book, System.out);
            /*
            输出
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <book>
                <bookName>三国演义</bookName>
                <id>100001</id>
                <price>20.5</price>
            </book>
             */
            // xml -> pojo
            String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                    "        <book>\n" +
                    "            <bookName>三国演义</bookName>\n" +
                    "            <id>100001</id>\n" +
                    "            <price>20.5</price>\n" +
                    "        </book>";
            Book retBook = MarshallerUtil.unmarshal(new StringReader(xml), Book.class);
            System.out.println(retBook);
        }
    }
    

JAX-WS

http://img.cana.space/picStore/20201109200110.png

JAX-WS可以完成wsdl到java的转换,即wsdl或合同契约优先。

http://img.cana.space/picStore/20201109200145.png

在[webservice介绍]({{ref “webservice介绍”}})一章里使用手写的client调用server就属于code first,我们可以使用jax-ws一键生成,直接完成wsdl到java的转换,即contract first。

使用wsdl2java工具将wsdl转换成Java类

  1. 从cxf官网下载apache-cxf-3.4.0.tar.gz

  2. 解压

    1
    
    $ tar -zxvf apache-cxf-3.4.0.tar.gz -C ~/soft
    
  3. 进入到bin目录下执行wsdl2java

    1
    2
    3
    4
    5
    6
    
    # david @ Davids-Macbook-Pro in ~/soft/apache-cxf-3.4.0/bin [20:10:22]
    $ pwd
    /Users/david/soft/apache-cxf-3.4.0/bin
    # 注意wsdlUrl 中的? 需要转义
    $ ./wsdl2java http://localhost:9999/cxf\?wsdl
    # 此时会在bin目录下生成一个com文件夹
    
  4. 将com文件夹复制到client工程里,注意这里不需要再引入cxf相关jar包, 工程结构如下所示

20201109201509

  1. 编写测试类调用服务端方法

    1
    2
    3
    4
    5
    6
    7
    8
    
    package com.eh.webservice.demo;
       
    public class ClientDemo {
        public static void main(String[] args) {
            HelloService helloService = new HelloServiceImplService().getHelloServiceImplPort();
            System.out.println(helloService.sayHello("徐达"));
        }
    }
    
  2. 控制台输出:

    1
    2
    
    objc[90096]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java (0x10750d4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1085244e0). One of the two will be used. Which one is undefined.
    hello, 徐达
    

重构client端工程

  1. 下面这4个文件暂时没用可以删除,将HelloService上的ObjectFactory注解去掉

    1
    2
    3
    4
    
    ObjectFactory
    package-info.java
    SayHello
    SayHelloResponse
    
  2. 打包客户端工程

    1
    
    mvn package
    
  3. mvn上传包,这里简单使用就直接放到lib中

  4. 删除HelloService和HelloServiceImplService

    20201109212011

  5. 现在的目录结构就很清晰了, 直接进行客户端调用也是ok的。

使用client参数一并生成客户端访问代码

1
$ ./wsdl2java -client http://localhost:9999/cxf\?wsdl