这是从Alessio Soldano编辑的Advanced JAX-WS Web Services手册中摘录的示例章节。
第一章介绍了自底向上创建Web服务端点的方法。 它允许非常快地将现有bean作为Web Service端点公开:在大多数情况下,将类转换为端点只需在代码中添加少量注释即可。
但是,当使用已定义的合同开发服务时,使用自顶向下方法要简单得多(有效),因为wsdl-to-java工具可以生成与WSDL匹配的带注释的代码。 这是在多种情况下(例如以下情况)的首选解决方案:
- 创建一个服务,该服务遵循预先开发的XML Schema和WSDL;
- 公开符合第三方规定的合同的服务(例如,使用已定义的一组消息调用该服务的供应商);
- 在保持与较旧客户端的兼容性的同时,替换现有Web Service的实现(不得更改合同)。
在下一节中,将提供一个自上而下的 Web Service端点开发示例,以及有关开发人员在编码时必须意识到的约束的一些详细信息,无论选择哪种方法。
使用自上而下的方法创建Web服务
为了建立一个包括Web服务端点和JAX-WS客户端的完整项目,我们将使用两个Maven项目。 第一个将是一个标准的webapp-javaee7项目,其中将包含Web服务端点。 第二个只是一个快速启动的Maven项目,它将对Web Service执行一个测试用例。
让我们像往常一样开始创建服务器项目:
mvn -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee7 -DarchetypeVersion=0.4-SNAPSHOT -DarchetypeRepository=https://nexus.codehaus.org/content/repositories/snapshots -DgroupId=com.itbuzzpress.chapter2.wsdemo -DartifactId=ws-demo2 -Dversion=1.0 -Dpackage=com.itbuzzpress.chapter2.wsdemo -Darchetype.interactive=false --batch-mode --update-snapshots archetype:generate
下一步将根据WSDL合同创建Web服务接口和存根。 步骤与为同一合同建立客户的步骤相似。 唯一的区别是wsconsume脚本会将生成的源文件输出到我们的Maven项目中:
$ wsconsume.bat -k CustomerService.wsdl -o ws-demo-wsdl\src\main\java
除了本章开始讨论的生成的类之外,我们还需要提供一个包含Web服务功能的服务端点实现 :
@WebService(endpointInterface="org.jboss.test.ws.jaxws.samples.webresult.Customer")
public class CustomerImpl implements Customer {public CustomerRecord locateCustomer(String firstName, String lastName, USAddress address) {CustomerRecord cr = new CustomerRecord();cr.setFirstName(firstName);cr.setLastName(lastName);return cr;}
}
端点实现类实现端点接口并通过@WebService批注引用它。 我们的WebService类什么也没做,只是使用接收到的参数作为输入创建一个CustomerRecord对象。 在一个真实的示例中,您将使用例如持久层来收集CustomerRecord。
一旦将实现类包含在项目中,则需要将项目打包并部署到目标容器,这将使用与该工具使用的相同的合约公开服务端点。
还可以在服务接口的@WebService wsdlLocation属性中引用本地WSDL文件,并将该文件包含在部署中。 这样可以准确地提供所提供的文档。
如果要将Web服务部署到WildFly应用程序服务器,则可以从管理控制台(如管理控制台)中检查端点现在是否可用。 选择“上层运行时”选项卡,然后单击“左侧子系统左侧”选项中包含的“ Web服务”链接:
JAX-WS端点的需求
无论选择哪种方法来开发JAX-WS端点,实际的实现都需要满足一些要求:
- 必须使用j avax.jws.WebService或javax.jws.WebServiceProvider批注对实现类进行批注。
- 实现类可以通过@WebService批注的endpointInterface元素显式引用服务终结点接口,但这不是必需的。 如果@WebService中没有指定endpointInterface,服务端点接口被隐含的实现类定义。
- 实现类的业务方法必须是公共的,并且不能声明为静态或最终的。
- javax.jws.WebMethod批注将用于公开给Web服务客户端的业务方法。 如果没有使用@WebMethod注释任何方法,则将公开所有业务方法。
- 向Web服务客户端公开的业务方法必须具有与JAXB兼容的参数和返回类型。
- 实现类不能声明为final,并且不能抽象。
- 实现类必须具有默认的公共构造函数,并且不能定义finalize方法。
- 实现类可以在其方法中为生命周期事件回调使用javax.annotation.PostConstruct或javax.annotation.PreDestroy注释。
构建和运行JAX-WS客户端的要求
JAX-WS客户端可以是任何Java项目的一部分,并且不需要明确要求它是部署在JavaEE容器上的JAR / WAR归档的一部分。 例如,客户端可以简单地包含在快速入门Maven项目中,如下所示:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=com.itbuzzpress.chapter2.wsdemo -DartifactId=client-demo-wsdl -Dversion=1.0 -Dpackage=com.itbuzzpress.chapter2.wsdemo -Dversion=1.0 -Darchetype.interactive=false --batch-mode
由于您的客户端需要引用端点接口和存根,因此需要提供它们或者从服务器项目复制它们,或者使用wsconsume再次生成它们:
$ wsconsume.bat -k CustomerService.wsdl -o client-demo-wsdl\src\main\java
现在包括一个最小的Client Test应用程序,它是JUnit测试用例的一部分:
public class AppTest extends TestCase {public void testApp() {CustomerService service = new CustomerService();Customer port = service.getCustomerPort();CustomerRecord record = port.locateCustomer("John", "Li", new USAddress()); System.out.println("Customer record is " +record);assertNotNull(record);}
}
编译并运行测试
为了成功运行WS客户端应用程序,需要正确设置类加载器,以包括所需的JAX-WS实现库(以及所需的传递依赖项(如果有))。 根据客户端要在其中运行的环境,这可能意味着向类路径添加了一些jar,或者向Maven依赖关系树添加了一些工件依赖项,正确设置了IDE等。
由于Maven用于构建包含客户端的应用程序,因此您可以按以下方式配置pom.xml ,使其包含对JBossWS的依赖关系:
<dependency><groupId>org.jboss.ws.cxf</groupId> <artifactId>jbossws-cxf-client</artifactId> <version>4.2.3.Final</version><scope>provided</scope>
</dependency>
现在,您可以执行测试用例,该用例将调用JAX-WS API以使用JBossWS服务客户端调用。
mvn clean package test
专注于客户端使用的JAX-WS实现
通过在应用程序类加载器中查找META-INF / services / javax.xml.ws.spi.Provider资源,可以在运行时选择要用于运行JAX-WS客户端的JAX-WS实现。 每个JAX-WS实现都有一个库(jar),该库包含该资源文件,该资源文件在内部引用实现JAX-WS SPI提供程序的适当类。
在WildFly 8.0.0.Final应用程序服务器上,JAX-WS实现包含在文件jbossws-cxf-factories-4.2.3.Final的META-INF / services / javax.xml.ws.spi.Provider中:
org.jboss.wsf.stack.cxf.client.ProviderImpl
因此,控制构建应用程序类加载器的类路径中包含哪些工件或jar库非常重要。 如果找到多个实现,则顺序很重要,因此将使用类路径中的第一个实现。
避免任何类路径问题(从而加载另一个JAX-WS实现)的最安全方法是将java.endorsed.dirs系统属性设置为包含jbossws-cxf-factories.jar; 如果不这样做,请确保没有在类路径之前包含其他META-INF / services / javax.xml.ws.spi.Provider资源,这将触发另一个JAX-WS实现。
最后,如果打算将JAX-WS客户端作为JavaEE应用程序的一部分在WildFly上运行,则将自动选择JBossWS JAX-WS实现来为客户端提供服务。
该摘录摘自“ Advanced JAX-WS Web Services ”一书,在该书中,您将学习基于SOAP的Web服务体系结构的概念,并获得有关在企业中构建和部署Web服务的实用建议。
本书从设置开发环境的基础知识和最佳实践入手,以清晰简洁的方式介绍了JAX-WS的内部细节。
您还将了解可用于创建,编译和测试SOAP Web服务的主要工具包,以及如何解决常见问题,例如调试数据和保护其内容。
您将从这本书中学到什么:
- 使用SOAP Web服务迈出第一步。 安装开发和测试应用程序所需的工具。
- 使用自上而下和自下而上的方法开发Web服务。
- 使用Maven原型加快Web服务的创建。
- 深入探讨JAX-WS类型的详细信息:Java到XML的映射以及XML到Java的映射
- 在WildFly 8和Tomcat上开发SOAP Web服务。 在WildFly上运行本机Apache CXF。
- 保护Web服务。 将身份验证策略应用于您的服务。 加密通信。
翻译自: https://www.javacodegeeks.com/2014/09/developing-a-top-down-web-service-project.html