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对象。
https://jcp.org/en/jsr/detail?id=224
https://jakarta.ee/specifications/xml-web-services/2.3/
https://jakarta.ee/specifications/xml-web-services/3.0/
https://jakarta.ee/specifications/xml-web-services/4.0/
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
主页:
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编程语言的平台无关性。
打开主页:https://eclipse-ee4j.github.io/metro-jax-ws/
点击右侧的Download就可以下载独立发布包,例如,下载jaxws-ri-4.0.0.zip。
解压后的目录:
设置CATALINA_HOME环境变量,指向Tomcat的安装目录,例如:
在cmd窗口,切换到Jakarta XML Web Services Eclipse实现解压后的目录,例如:D:\jaxws-ri-4.0.0\jaxws-ri
运行ant install命令。这个命令其实执行了两个大的操作:
build.xml文件片段:
https://eclipse-ee4j.github.io/metro-jax-ws/4.0.0/docs/release-documentation.html#jar-dependency
fromjava这个样例演示了从一个Java service endpoint的实现开始,如何构建、部署、调用一个简单的web服务。其中Java service endpoint的实现使用了Java注释。
服务实现类只有一个方法addNumbers,输入两个整数,返回一个整数,抛出AddNumbersException异常:
运行web服务有两种方式:
运行ant clean的作用是删掉${build.home}
目录。其中${build.home}
目录指向${basedir}/build
,就是fromjava/build
目录。(其实这个命令不运行也可以,因为下一步运行ant server命令的时候其中含有ant clean的步骤)
运行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
因为生成客户端代码的时候要访问web服务动态生成的wsdl文件,所以要先启动tomcat。
部署以后的文件布局:
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
访问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 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表示运行客户端。
<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 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文件:
另外打开一个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
<target name="server-j2se-stop" depends="setup">
<get src="http://localhost:9090/stop" dest="stop.status"/>
</target>
在maven工程的pom.xml文件中增加如下依赖:
jakarta.xml.ws
jakarta.xml.ws-api
4.0.0
com.sun.xml.ws
jaxws-rt
4.0.0