说明
基于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>
http响应报文体的xml数据:
<?xml version='1.0' encoding='UTF-8'?>
<response>
<body>15</body>
<flag>1</flag>
</response>
代码实现
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>
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;
}
}
}
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;
}
}
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;
}
}
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/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
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>
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