说明
基于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.StAXSourceSystem.out.println(source.getClass().getName());//注意,此处的StAXSource是com.sun.xml.ws.util.xml.StAXSource// 而不是javax.xml.transform.stax.StAXSourceif (source instanceof StAXSource) {// 参数中填写用JAXB注解的请求和响应类,它们分别对应请求的xml和响应的xmlJAXBContext 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.RegisterRequestSystem.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);// 用输入流构造StreamSourcereturn 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"?><endpointsxmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"version="2.0"><endpointname="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│ └─libangus-activation-1.0.0.jarangus-mail-1.0.0.jarFastInfoset-2.1.0.jargmbal-api-only-4.0.3.jarha-api-3.1.13.jarjakarta.activation-api-2.1.0.jarjakarta.annotation-api-2.1.1.jarjakarta.mail-api-2.1.0.jarjakarta.xml.bind-api-4.0.0.jarjakarta.xml.soap-api-3.0.0.jarjakarta.xml.ws-api-4.0.0.jarjaxb-core-4.0.0.jarjaxb-impl-4.0.0.jarjaxws-rt-4.0.0.jarlog4j-api-2.20.0.jarlog4j-core-2.20.0.jarmanagement-api-3.2.3.jarmimepull-1.10.0.jarsaaj-impl-3.0.0.jarstax-ex-2.1.0.jarstax2-api-4.2.1.jarstreambuffer-2.1.0.jarwoodstox-core-6.2.8.jar