简介
JAX-WS(Java API for XML-Based Web Services),是创建web服务的Java编程接口,特别是SOAP服务。是Java XML编程接口之一,是Java SE 和Java EE 平台的一部分。
JAX-WS 2.0 规范是代替JAX-RPC 1.0的下一代Web服务API。JAX-RPC(The Java API for XML Based RPC)是基于XML的RPC(远程过程调用)的Java API。
JAX-WS 2.0 使用JAXB(The Java Architecture for XML Binding)进行XML数据绑定,所谓绑定就是指XML请求和XML响应如何映射成java对象。
参考资源
JAX-WS 2.0参考资源
https://jcp.org/en/jsr/detail?id=224
https://jakarta.ee/specifications/xml-web-services/2.3/
JAX-WS 3.0参考资源
https://jakarta.ee/specifications/xml-web-services/3.0/
JAX-WS 4.0参考资源
https://jakarta.ee/specifications/xml-web-services/4.0/
Jakarta Web Services Metadata
Jakarta Web Services Metadata项目是Jakarta XML Web Services 项目的一部分,它用Java为web 服务定义了一个编程模型。
代码库:https://github.com/jakartaee/jws-api
Jakarta Web Services Metadata 3.0 Specification Document (HTML):
https://jakarta.ee/specifications/web-services-metadata/3.0/ws-metadata-spec-3.0
Jakarta Web Services Metadata 3.0 Javadoc:
https://jakarta.ee/specifications/web-services-metadata/3.0/apidocs/jakarta.jws/module-summary.html
参考实现
旧项目(已经归档、只读)
https://javaee.github.io/metro-jax-ws/
https://github.com/javaee/metro-jax-ws
新项目(Jakarta XML Web Services Eclipse 实现)
主页:
https://eclipse-ee4j.github.io/metro-jax-ws/
代码库:
https://github.com/eclipse-ee4j/metro-jax-ws
XML web服务的Eclipse 实现是一个web服务框架,它为最终用户和中间件开发者开发web服务解决方案提供了工具和基础设施(infrastructure)。
使用XML web服务的Eclipse 实现,客户端和web有一个大的优势:Java编程语言的平台无关性。
Jakarta XML Web Services Eclipse 实现需要的软件
- Java SE 11或以后版本
- Ant 1.10.6或以后版本
- 在GlassFish v7.x 、Apache Tomcat 10.1.x下测试过
安装Jakarta XML Web Services Eclipse 实现
下载Jakarta XML Web Services Eclipse实现独立zip发布包
打开主页:https://eclipse-ee4j.github.io/metro-jax-ws/
点击右侧的Download就可以下载独立发布包,例如,下载jaxws-ri-4.0.0.zip。
解压后的目录:
bin子目录下的内容:
docs子目录下的内容:
lib子目录下的内容:
samples子目录下的内容:
安装到Tomcat中
设置CATALINA_HOME环境变量,指向Tomcat的安装目录,例如:
在cmd窗口,切换到Jakarta XML Web Services Eclipse实现解压后的目录,例如:D:\jaxws-ri-4.0.0\jaxws-ri
这个目录下有build.xml文件:
运行ant install命令。这个命令其实执行了两个大的操作:
- 拷贝Jakarta XML Web Services Eclipse实现lib子目录下的jar文件到Tomcat安装目录下面的/shared/lib子目录中
- 更新Tomcat安装目录下面/conf/catalina.properties文件中的属性shared.loader,使之等于${catalina.home}/shared/lib/*.jar
build.xml文件片段:
<target name="install" depends="update-catalina-props" description="Install XML-WS RI 4.0.0 jars">
<echo message="Installing XML-WS RI 4.0.0 for ${catalina.home} ..."/>
<mkdir dir="${catalina.lib.home}"/>
<copy toDir="${catalina.lib.home}" overwrite="true">
<fileset dir="${basedir}/lib" includes="*.jar"/>
</copy>
</target>
<target name="update-catalina-props">
<echo message="Backing up ${catalina.home}/conf/catalina.properties..."/>
<copy file="${catalina.home}/conf/catalina.properties" tofile="${catalina.home}/conf/catalina.properties.backup"/>
<echo message="Adding XML-WS RI jars to shared.loader property in ${catalina.home}/conf/catalina.properties..."/>
<replace file="${catalina.home}/conf/catalina.properties" token="shared.loader=" value="shared.loader=$${catalina.home}/shared/lib/*.jar,"/>
</target>
执行ant install命令的窗口输出信息:
Jakarta XML Web Services Eclipse 实现依赖的jar包
https://eclipse-ee4j.github.io/metro-jax-ws/4.0.0/docs/release-documentation.html#jar-dependency
SOAP1.1+HTTP样例:运行fromjava样例(来自Jakarta XML Web Services Eclipse实现发布包)
说明
fromjava这个样例演示了从一个Java service endpoint的实现开始,如何构建、部署、调用一个简单的web服务。其中Java service endpoint的实现使用了Java注释。
fromjava的目录结构:
服务实现类只有一个方法addNumbers,输入两个整数,返回一个整数,抛出AddNumbersException异常:
运行web服务有两种方式:
- 在servlet容器中运行
- 作为一个j2se webservice endpoint运行(不需要servlet容器)
运行方式一:在tomcat容器中运行web服务
设置环境变量JAXWS_HOME指向JAX-WS的安装目录
在cmd窗口切换到fromjava的目录
运行ant clean
运行ant clean的作用是删掉${build.home}
目录。其中${build.home}
目录指向${basedir}/build
,就是fromjava/build
目录。(其实这个命令不运行也可以,因为下一步运行ant server命令的时候其中含有ant clean的步骤)
运行ant server -Dtomcat=true
运行ant server -Dtomcat=true的作用是构建、部署web服务的WAR包,因为要将web服务运行在tomcat中,所以加了-Dtomcat=true这个属性。这个命令做了四个工作:
<target name="server" depends="setup">
<antcall target="clean"/>
<antcall target="build-server-java"/>
<antcall target="create-war"/>
<antcall target="deploy"/>
</target>
运行输出:
现在fromjava目录下的文件布局(注:照理${env.AS_HOME}
这个目录不应该生成的,对我们没有什么用):
D:\JAXWS-RI-4.0.0\JAXWS-RI\SAMPLES\FROMJAVA
│ build.xml
│ Readme.txt
│
├─${env.AS_HOME}
│ └─domains
│ └─domain1
│ └─autodeploy
│ jaxws-fromjava.war
│
├─build
│ ├─classes
│ │ └─fromjava
│ │ └─server
│ │ │ AddNumbersException.class
│ │ │ AddNumbersImpl.class
│ │ │ AddWebservice.class
│ │ │ EndpointStopper$1.class
│ │ │ EndpointStopper.class
│ │ │
│ │ └─jaxws
│ │ AddNumbers.class
│ │ AddNumbers.java
│ │ AddNumbersExceptionBean.class
│ │ AddNumbersExceptionBean.java
│ │ AddNumbersResponse.class
│ │ AddNumbersResponse.java
│ │
│ └─war
│ jaxws-fromjava.war
│
├─etc
│ deploy-targets.xml
│ sun-jaxws.xml
│ web.xml
│
└─src
└─fromjava
├─client
│ AddNumbersClient.java
│
└─server
AddNumbersException.java
AddNumbersImpl.java
AddWebservice.java
EndpointStopper.java
到<tomcat安装目录>/webapps
下查看,war包已经拷贝过来了:
运行tomcat
因为生成客户端代码的时候要访问web服务动态生成的wsdl文件,所以要先启动tomcat。
到<tomcat安装目录>/webapps
下查看,war包已经被自动部署了:
部署以后的文件布局:
D:\APACHE-TOMCAT-10.1.13\WEBAPPS\JAXWS-FROMJAVA
├─META-INF
│ MANIFEST.MF
│ war-tracker
│
└─WEB-INF
│ sun-jaxws.xml
│ web.xml
│
└─classes
└─fromjava
└─server
│ AddNumbersException.class
│ AddNumbersImpl.class
│ AddWebservice.class
│ EndpointStopper$1.class
│ EndpointStopper.class
│
└─jaxws
AddNumbers.class
AddNumbers.java
AddNumbersExceptionBean.class
AddNumbersExceptionBean.java
AddNumbersResponse.class
AddNumbersResponse.java
看看wsdl文件能否正常生成
访问http://localhost:8080/jaxws-fromjava/addnumbers?wsdl
可以看到,正常生成了wsdl文件。生成客户端代码的时候,就要访问这个wsdl的地址。
<?xml version='1.0' encoding='UTF-8'?><!-- Published by XML-WS Runtime (https://github.com/eclipse-ee4j/metro-jax-ws). Runtime's version is XML-WS Runtime 4.0.0 git-revision#129f787. --><!-- Generated by XML-WS Runtime (https://github.com/eclipse-ee4j/metro-jax-ws). Runtime's version is XML-WS Runtime 4.0.0 git-revision#129f787. --><definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://server.fromjava/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://server.fromjava/" name="AddNumbersImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://server.fromjava/" schemaLocation="http://localhost:8080/jaxws-fromjava/addnumbers?xsd=1"/>
</xsd:schema>
</types>
<message name="addNumbers">
<part name="parameters" element="tns:addNumbers"/>
</message>
<message name="addNumbersResponse">
<part name="parameters" element="tns:addNumbersResponse"/>
</message>
<message name="AddNumbersException">
<part name="fault" element="tns:AddNumbersException"/>
</message>
<portType name="AddNumbersImpl">
<operation name="addNumbers">
<input wsam:Action="http://server.fromjava/AddNumbersImpl/addNumbersRequest" message="tns:addNumbers"/>
<output wsam:Action="http://server.fromjava/AddNumbersImpl/addNumbersResponse" message="tns:addNumbersResponse"/>
<fault message="tns:AddNumbersException" name="AddNumbersException" wsam:Action="http://server.fromjava/AddNumbersImpl/addNumbers/Fault/AddNumbersException"/>
</operation>
</portType>
<binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="addNumbers">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
<fault name="AddNumbersException">
<soap:fault name="AddNumbersException" use="literal"/>
</fault>
</operation>
</binding>
<service name="AddNumbersImplService">
<port name="AddNumbersImplPort" binding="tns:AddNumbersImplPortBinding">
<soap:address location="http://localhost:8080/jaxws-fromjava/addnumbers"/>
</port>
</service>
</definitions>
运行ant clean
运行ant clean:
运行ant client
运行ant client的目的是为了生成客户端代码并编译:
<target name="generate-client" depends="setup">
<wsimport
debug="true"
verbose="${verbose}"
keep="true"
destdir="${build.classes.home}"
package="fromjava.client"
wsdl="http://localhost:8080/jaxws-fromjava/addnumbers?wsdl">
</wsimport>
</target>
<target name="client" depends="generate-client">
<javac
fork="true"
srcdir="${basedir}/src"
destdir="${build.classes.home}"
includes="**/client/**,**/common/**">
<classpath refid="jaxws.classpath"/>
</javac>
</target>
运行后,客户端代码布局:
D:\JAXWS-RI-4.0.0\JAXWS-RI\SAMPLES\FROMJAVA\BUILD
├─classes
│ └─fromjava
│ └─client
│ AddNumbers.class
│ AddNumbers.java
│ AddNumbersClient.class
│ AddNumbersException.class
│ AddNumbersException.java
│ AddNumbersException_Exception.class
│ AddNumbersException_Exception.java
│ AddNumbersImpl.class
│ AddNumbersImpl.java
│ AddNumbersImplService.class
│ AddNumbersImplService.java
│ AddNumbersResponse.class
│ AddNumbersResponse.java
│ ObjectFactory.class
│ ObjectFactory.java
│ package-info.class
│ package-info.java
│
└─war
运行ant run
执行ant run表示运行客户端。
<target name="run">
<java fork="true" classname="fromjava.client.AddNumbersClient">
<classpath>
<path refid="jaxws.classpath"/>
<pathelement location="${build.classes.home}"/>
<pathelement location="${basedir}/etc"/>
</classpath>
</java>
</target>
在运行ant run前,启动Wireshark抓包工具,在环回接口上抓包,目的是看看调用web服务的协议是否用了SOAP协议(用http过滤):
计算10+20的请求:
计算10+20的响应:
计算-10+20的请求:
计算-10+20的响应:
运行方式二:作为一个j2se webservice endpoint运行(不运行在servlet容器中)
运行ant clean server-j2se
运行ant clean server-j2se生成服务端代码,并且用Endpoint API来部署:
<target name="server-j2se" depends="setup">
<antcall target="clean"/>
<antcall target="build-server-java"/>
<echo message="Starting endpoint... To stop: ant server-j2se-stop "/>
<java fork="true" classname="fromjava.server.AddWebservice">
<classpath>
<path refid="jaxws.classpath"/>
<pathelement location="${build.classes.home}"/>
</classpath>
</java>
</target>
生成的文件布局:
D:\JAXWS-RI-4.0.0\JAXWS-RI\SAMPLES\FROMJAVA\BUILD
├─classes
│ └─fromjava
│ └─server
│ │ AddNumbersException.class
│ │ AddNumbersImpl.class
│ │ AddWebservice.class
│ │ EndpointStopper$1.class
│ │ EndpointStopper.class
│ │
│ └─jaxws
│ AddNumbers.class
│ AddNumbers.java
│ AddNumbersExceptionBean.class
│ AddNumbersExceptionBean.java
│ AddNumbersResponse.class
│ AddNumbersResponse.java
│
└─war
访问http://localhost:8080/jaxws-fromjava/addnumbers?wsdl
可以正常生成wsdl文件:
运行ant clean client run
另外打开一个cmd窗口,运行ant clean client run,目的是在根据endpoint发布的wsdl文件生成客户端代码、编译、并且运行。
运行后,客户端的代码布局:
D:\JAXWS-RI-4.0.0\JAXWS-RI\SAMPLES\FROMJAVA\BUILD
├─classes
│ └─fromjava
│ └─client
│ AddNumbers.class
│ AddNumbers.java
│ AddNumbersClient.class
│ AddNumbersException.class
│ AddNumbersException.java
│ AddNumbersException_Exception.class
│ AddNumbersException_Exception.java
│ AddNumbersImpl.class
│ AddNumbersImpl.java
│ AddNumbersImplService.class
│ AddNumbersImplService.java
│ AddNumbersResponse.class
│ AddNumbersResponse.java
│ ObjectFactory.class
│ ObjectFactory.java
│ package-info.class
│ package-info.java
│
└─war
运行ant server-j2se-stop,停止web服务
<target name="server-j2se-stop" depends="setup">
<get src="http://localhost:9090/stop" dest="stop.status"/>
</target>
Jakarta XML Web Services Eclipse实现下载方式二:用maven下载
在maven工程的pom.xml文件中增加如下依赖:
<dependencies>
<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>
</dependencies>