• 代码示例:基于JAX-WS和JAXB,其中http请求和响应的报文体都是xml数据


    说明

    基于JAX-WS编写了RESTful的web服务端点。
    http请求和响应的报文体都是xml数据,服务端分别对应了用JAXB注解的请求和响应类。
    只实现了服务端的代码示例
    客户端使用了Postman

    示例

    要实现的目标:http请求和响应报文体的xml数据

    http请求报文体的xml数据:

    <?xml version="1.0" encoding="UTF-8"?>
    <request>
        <reqtype>01</reqtype>
        <secret>test</secret>
        <body>0858032316</body>
    </request>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    http响应报文体的xml数据:

    <?xml version='1.0' encoding='UTF-8'?>
    <response>
        <body>15</body>
        <flag>1</flag>
    </response>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码实现

    maven工程增加依赖

    maven工程的pom.xml文件中增加如下依赖:

    <dependency>
      <groupId>jakarta.xml.ws</groupId>
      <artifactId>jakarta.xml.ws-api</artifactId>
      <version>4.0.0</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.ws</groupId>
      <artifactId>jaxws-rt</artifactId>
      <version>4.0.0</version>        
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    RESTful的web服务端点实现

    package com.thb.server.register;
    
    import com.sun.xml.ws.util.xml.StAXSource;
    
    import javax.xml.transform.Source;
    import javax.xml.transform.stream.StreamSource;
    
    import jakarta.xml.bind.JAXBContext;
    import jakarta.xml.bind.JAXBException;
    import jakarta.xml.bind.Marshaller;
    import jakarta.xml.bind.Unmarshaller;
    import jakarta.xml.ws.BindingType;
    import jakarta.xml.ws.Provider;
    import jakarta.xml.ws.WebServiceProvider;
    import jakarta.xml.ws.http.HTTPBinding;
    import jakarta.xml.ws.http.HTTPException;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    
    @WebServiceProvider
    @BindingType(value=HTTPBinding.HTTP_BINDING)
    public class Register implements Provider<Source> {
    
        public Source invoke(Source source) {
            try {
                return process(source);
            } catch(Exception e) {
                e.printStackTrace();
                throw new HTTPException(500);
            }
        }
    
        private Source process(Source source) throws JAXBException { 
            // 传入的是xml数据时,此处source是com.sun.xml.ws.util.xml.StAXSource
            System.out.println(source.getClass().getName());
    
            //注意,此处的StAXSource是com.sun.xml.ws.util.xml.StAXSource
            // 而不是javax.xml.transform.stax.StAXSource
            if (source instanceof StAXSource) {
                // 参数中填写用JAXB注解的请求和响应类,它们分别对应请求的xml和响应的xml
                JAXBContext context = JAXBContext.newInstance(RegisterResponse.class,
                        RegisterRequest.class);
    
                // 下面代码将收到的请求中的xml数据反序列化为Java对象
                // 创建一个Unmarshaller,反序列化使用
                Unmarshaller unmarshaller = context.createUnmarshaller();
                // 将接收到的xml数据反序列到java对象
                Object object = unmarshaller.unmarshal(source);
                // 打印出来反序列化后的Java对象的类型,是com.thb.server.register.RegisterRequest
                System.out.println(object.getClass().getName());
                // 将反序列化后的Java对象转换为RegisterRequest对象,RegisterRequest使用了JAXB注解
                RegisterRequest registerRequest = (RegisterRequest)object;
                // 将反序列化以后的Java对象的属性打印出来,看是否符合预期
                System.out.println("functionCode: " + registerRequest.getFunctionCode());
                System.out.println("enterpriseAccount: " + registerRequest.getEnterpriseAccount());
                System.out.println("secret: " + registerRequest.getSecret());
    
                // 下面代码将Java对象序列化为xml数据
                // 创建一个Marshaller,序列化使用
                Marshaller marshaller = context.createMarshaller();
                // 设置序列化后的xml的编码类型。此处不设置也可以
                marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
                // 创建一个输出输出流
                ByteArrayOutputStream  outputStream = new ByteArrayOutputStream();
                // 创建响应的java对象,并设置对象的属性,该对象使用了JAXB注解
                RegisterResponse registerResponse = new RegisterResponse();
                registerResponse.setFlag(1);
                registerResponse.setEnterpriseId("15");
                // 将Java对象序列到输出流
                marshaller.marshal(registerResponse, outputStream);
                // 取输出流中的字节
                byte[] bytes = outputStream.toByteArray();
                // 构造输入流
                ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
                // 用输入流构造StreamSource
                return new StreamSource(inputStream);
            } else {
                return null;
            }
        }
        
    }
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    http请求xml对应的java对象,使用了JAXB注解

    package com.thb.server.register;
    
    import jakarta.xml.bind.annotation.XmlElement;
    import jakarta.xml.bind.annotation.XmlRootElement;
    
    /**
     * 该类映射到http请求的xml
     * @author thb
     *
     */
    // 使用了JAXB注解,映射到xml中的request元素
    @XmlRootElement(name = "request")
    public class RegisterRequest {
    
        private int functionCode;
    
        private String secret;
    
        private String enterpriseAccount;
    
        // 使用了JAXB注解,映射到xml中的reqtype元素
        @XmlElement(name="reqtype")
        public int getFunctionCode() {
            return this.functionCode;
        }
    
        // 此处的setter函数要有,否则从xml反序列到java对象的时候无法赋值
        public void setFunctionCode(int functionCode) {
            this.functionCode = functionCode;
        }
    
        // 使用了JAXB注解,映射到xml中的secret元素
        @XmlElement(name="secret")
        public String getSecret() {
            return this.secret;
        }
    
        // 此处的setter函数要有,否则从xml反序列到java对象的时候无法赋值
        public void setSecret(String secret) {
            this.secret = secret;
        }
    
        // 使用了JAXB注解,映射到xml中的body元素
        @XmlElement(name = "body")
        public String getEnterpriseAccount() {
            return this.enterpriseAccount;
        }
    
        // 此处的setter函数要有,否则从xml反序列到java对象的时候无法赋值
        public void setEnterpriseAccount(String enterpriseAccount) {
            this.enterpriseAccount = enterpriseAccount;
        }
    }
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    http响应xml对应的java对象,使用了JAXB注解

    package com.thb.server.register;
    
    import jakarta.xml.bind.annotation.XmlElement;
    import jakarta.xml.bind.annotation.XmlRootElement;
    
    /**
     * 该类映射到http响应的xml
     * @author thb
     *
     */
    //使用了JAXB注解,映射到xml中的response元素
    @XmlRootElement(name = "response")
    public class RegisterResponse {
    
        private int flag;
    
        private String enterpriseId;
    
        public RegisterResponse() {}
    
        //使用了JAXB注解,映射到xml中的flag元素
        @XmlElement(name = "flag")
        public int getFlag() {
            return this.flag;
        }
    
        public void setFlag(int flag) {
            this.flag = flag;
        }
    
        //使用了JAXB注解,映射到xml中的body元素
        @XmlElement(name = "body")
        public String getEnterpriseId() {
            return this.enterpriseId;
        }
    
        public void setEnterpriseId(String enterpriseId) {
            this.enterpriseId = enterpriseId;
        }
    
    }
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    web应用的web.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app version="6.0" xmlns="https://jakarta.ee/xml/ns/jakartaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd">
        <description>power-restful</description>
        <display-name>power-restful</display-name>
        <listener>
            <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
        </listener>
        <servlet>
            <description>The JAX-WS dispatcher servlet</description>
            <display-name>dispatcher</display-name>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/register/*
        
        
            60
        
    
    
    • 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

    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="restful-register"
            implementation="com.thb.server.register.Register"
            url-pattern="/register/*" />
    </endpoints>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    web应用部署到tomcat的目录布局

    D:\APACHE-TOMCAT-10.1.13\WEBAPPS\POWER-RESTFUL
    ├─META-INF
    │      MANIFEST.MF
    │      war-tracker
    │      
    └─WEB-INF
        │  sun-jaxws.xml
        │  web.xml
        │  
        ├─classes
        │  └─com
        │      └─thb
        │          └─server
        │              └─register
        │                      Register.class
        │                      RegisterRequest.class
        │                      RegisterResponse.class
        │                      
        └─lib
                angus-activation-1.0.0.jar
                angus-mail-1.0.0.jar
                FastInfoset-2.1.0.jar
                gmbal-api-only-4.0.3.jar
                ha-api-3.1.13.jar
                jakarta.activation-api-2.1.0.jar
                jakarta.annotation-api-2.1.1.jar
                jakarta.mail-api-2.1.0.jar
                jakarta.xml.bind-api-4.0.0.jar
                jakarta.xml.soap-api-3.0.0.jar
                jakarta.xml.ws-api-4.0.0.jar
                jaxb-core-4.0.0.jar
                jaxb-impl-4.0.0.jar
                jaxws-rt-4.0.0.jar
                log4j-api-2.20.0.jar
                log4j-core-2.20.0.jar
                management-api-3.2.3.jar
                mimepull-1.10.0.jar
                saaj-impl-3.0.0.jar
                stax-ex-2.1.0.jar
                stax2-api-4.2.1.jar
                streambuffer-2.1.0.jar
                woodstox-core-6.2.8.jar
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    用Postman发送请求、收到的响应

    在这里插入图片描述

  • 相关阅读:
    带你一起理解什么是数据库分片?
    高效批量剪辑,轻松缩小视频尺寸!一键解决视频文件大小问题!
    Bean对象的作用域
    使用项目管理系统优化公众号文章排期
    javase javaee javame
    golang保留小数点后两位,不四舍五入
    visual studio解决bug封装dll库
    基于web的邮票鉴赏系统及实现设计与实现-计算机毕业设计源码+LW文档
    Jetpack系列 -- LiveData源码原理解析(解决黏性问题)
    Pandas 入门指南
  • 原文地址:https://blog.csdn.net/panghuangang/article/details/134477666