Apache CXF - 简介

在当今的环境中,您可以使用多个选项来创建 Web 服务应用程序。您可以使用多种标准和广泛接受的协议中的一种或多种进行通信。例如SOAP、XML/HTTP、RESTful HTTP和CORBA(通用对象请求代理架构,在过去非常流行,但现在不常用。

您还可以选择不同的传输方式,例如 HTTP、JMS、JBI和前端 API,例如JAX-RS和JAX-WS。有这么多的 Web 服务开发选项,需要一个开源服务框架来将上述所有选项粘合在一起,这就是Apache CXF所做的。

在本教程中,您将学习如何使用我们上面列出的一个或多个选项,使用 CXF 创建 Web 服务和使用该服务的客户端。本教程将引导您完成服务器和客户端的整个代码开发。由于每个应用程序只能使用每个类别中的一个选项,即前端、传输和协议,考虑到这三者的所有排列和组合,应用程序的数量将非常高。

本教程详细讨论了以下项目的开发 -

  • 具有普通旧 Apache CXF 对象 (POJO) 的 CXF

  • 带有 JAX-WS 的 CXF

  • 带有 WSDL 的 CXF

  • 带有 JAX-RS 的 CXF

  • 带有 JMS 的 CXF

为了简单起见,我们使用了带有命令行界面的 maven。你可以使用你喜欢的 IDE 来创建一个 Maven 项目。

在下一章中,让我们从第一个开始。

带有 POJO 的 Apache CXF

在本章中,您将学习如何开发一个向用户发送问候消息的简单 Web 应用程序。Web 服务项目使用WSDL模型。CXF 允许您通过提供一个简单的前端将 Apache CXF API 映射到底层 WSDL 来隐藏此 WSDL 模型。

在这个最简单的项目中,Web 服务的接口将直接暴露给客户端,客户端将使用本机 Apache CXF API 来调用 Web 服务。

首先,我们将创建一个 Web 服务。每个服务都有一个向客户端公开的接口。我们可以将此接口编写为简单的 Apache CXF 接口或 WSDL 文档。在这种 Apache CXF-First 方法中,我们将通过 Apache CXF 接口公开我们的服务。

开发 Web 服务

我们要在 Web 上创建的服务将有一个称为greetings 的Web 方法。该方法采用字符串类型参数,我们将在其中发送用户名。该服务将向呼叫者发送回问候消息,并在消息中包含收到的用户名。

网络服务接口

为了公开我们的 Web 服务的接口,我们将创建一个 Apache CXF 接口,如下所示 -

//HelloWorld.java
package com.tutorialspoint.cxf.pojo;
public interface HelloWorld {String greetings(String text);
}

该接口只有一种方法,称为greetings。服务器将实现这个接口。在我们简单的应用程序中,这个接口直接暴露给客户端。通常,在 Web 服务应用程序中,您使用 WSDL 来描述 Web 服务接口。在这个简单的应用程序中,我们将向客户端开发人员提供这个直接接口。然后客户端将调用服务器对象上的问候消息。因此,首先让我们创建 Web 服务。

网络服务实现

所述的HelloWorld接口在实施HelloWorldImpl阿帕奇CXF类如下所示-

//HelloWorldImpl.java
package com.tutorialspoint.cxf.pojo;
public class HelloWorldImpl implements HelloWorld {@Overridepublic String greetings(String text) {return "Hi " + text;}
}

问候方法接收的参数类型,其附加到一个问候消息,并返回结果字符串到调用者。

接下来,我们编写服务器应用程序来托管HelloWorld服务。

创建服务器

服务器应用程序由两部分组成 -

  • 第一部分为我们的 Web 服务创建一个工厂,然后

  • 第二部分编写了一个实例化它的主要方法。

服务器使用CXF 库提供的ServerFactoryBean类向远程客户端公开我们的HelloWorld接口。因此,我们首先实例化ServerFactoryBean类,然后设置它的各种属性 -

ServerFactoryBean factory = new ServerFactoryBean();

我们通过调用工厂对象的setServiceClass方法来设置要调用的服务类-

factory.setServiceClass(HelloWorld.class);

我们通过调用工厂的setAddress方法来设置调用我们服务的 URL 。请注意,该服务将在此 URL 上发布。

factory.setAddress("http://localhost:5000/Hello");

在这种情况下,该服务部署在嵌入式服务器上,并将监听端口 5000。您可以选择您选择的任何端口号。

在创建工厂之前,你需要告诉工厂我们的服务实现类。这是通过调用工厂对象的setServiceBean方法来完成的,如下所示 -

factory.setServiceBean(new HelloWorldImpl());

服务 bean 设置为我们的服务实现类的实例。最后,我们通过调用它的create方法来创建工厂-

<span style="color:#000000">factory.create();
</span>

现在,由于我们已经开发了工厂来运行我们的 Web 服务,接下来我们将编写一个main方法来实例化它并让它运行一段时间。

现在,编写一个main方法来实例化HelloServer类,如下所示 -

<span style="color:#000000">public static void main(String[] args) throws Exception {new HelloServer();System.out.println("Listening on port 5000 ...");
}
</span>

一旦实例化,HelloServer类将无限期地继续运行。对于生产部署,你肯定会让你的服务器永远运行。在当前情况下,我们将在预定时间后终止服务器,如下所示 -

<span style="color:#000000">Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);
</span>

HelloServer类的完整代码如下 -

<span style="color:#000000">//HelloServer.java
</span>
<span style="color:#000000">//HelloServer.java
package com.tutorialspoint.cxf.pojo;
import org.apache.cxf.frontend.ServerFactoryBean;
public class HelloServer {protected HelloServer() throws Exception {ServerFactoryBean factory = new ServerFactoryBean();factory.setServiceClass(HelloWorld.class);factory.setAddress("http://localhost:5000/Hello");factory.setServiceBean(new HelloWorldImpl());factory.create();}public static void main(String[] args) throws Exception {new HelloServer();System.out.println("Listening on port 5000 ...");Thread.sleep(5 * 60 * 1000);System.out.println("Server exiting ...");System.exit(0);}
}
</span>

我们创建的服务器应用程序使用CXF 库中的ServerFactoryBean类。我们现在必须在我们的项目中包含这些库才能成功编译HelloServer类。我们将使用Maven来设置项目依赖项。

设置 Maven 项目

要创建 Maven 项目,请在命令行窗口中键入以下命令。请注意,我们已经在 Mac 机器上对此进行了测试。对于 Windows 和 Linux 安装,说明可能在几个地方有所不同。

<span style="color:#000000">mvn archetype:generate
</span>

当询问属性时,输入以下值 -

<span style="color:#000000">Define value for property 'groupId': : <strong>com.tutorialspoint</strong>
Define value for property 'artifactId': : <strong>cxf-pojo</strong>
Define value for property 'version': 1.0-SNAPSHOT: : <strong>1.0</strong>
Define value for property 'package': com.tutorialspoint: : <strong>com.tutorialspoint.cxf.pojo</strong>
</span>

完成 maven 命令后,您将找到在当前文件夹中创建的适当文件夹结构以及 pom.xml 文件。

生成的目录结构如下所示 -

您将在pom.xml 中添加 CXF 依赖项,并将上面创建的 Apache CXF 文件复制到 maven 创建结构的相应文件夹中。供您参考,我们在下面给出了我们在机器上创建的项目的 pom.xml 文件。

<span style="color:#000000"><?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tutorialspoint</groupId><artifactId>cxf-pojo</artifactId><version>1.0</version><packaging>jar</packaging><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.pojo.HelloServer</mainClass></configuration></execution></executions></plugin></plugins></build></profile><profile><id>client</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.pojo.HelloClient</mainClass></configuration></execution></executions></plugin></plugins></build></profile></profiles><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-features-logging</artifactId><version>3.3.0</version><type>jar</type></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-simple</artifactId><version>3.3.0</version><type>jar</type></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.3.0</version></dependency><!-- Jetty is needed if you're using the CXFServlet --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties>
</project>
</span>

上面的 pom.xml 可能包含与本项目无关的附加依赖项,但在本教程中的下一个项目中是必需的。无论如何,包含额外的依赖项并没有什么坏处。

项目文件夹结构

放置服务器和客户端 Apache CXF 文件后,我机器上的项目文件夹结构如下所示,供您快速参考 -

运行服务器

要构建项目,请在命令行窗口中使用以下命令 -

<span style="color:#000000">mvn clean install
</span>

您可以使用以下命令启动服务器 -

<span style="color:#000000">mvn -Pserver
</span>

这将启动服务器,您将在控制台上看到以下提示 -

<span style="color:#000000">INFO: Creating Service {http://pojo.cxf.tutorialspoint.com/}HelloWorld from class com.tutorialspoint.cxf.pojo.HelloWorld
INFO: Setting the server's publish address to be http://localhost:5000/Hello
Listening on port 5000 ...
</span>

现在,在您的浏览器窗口中指定我们已发布服务的 URL。您将看到以下输出 -

这确认我们的服务正在本地主机上的指定端口上运行。由于我们没有在调用中指定问候消息,因此会向浏览器返回 SOAP 错误消息。

您可以使用您选择的 SOAP 客户端进一步测试您的 Web 服务。这里我们使用Postman来测试我们的服务器。

输出如下所示 -

观察SOAP 请求是手动编码的。发布请求后,服务器发送了一个SOAP 响应消息,该消息显示在屏幕截图的底部。

由此,您可以理解 CXF 保持对请求和响应的 SOAP 协议的使用,同时为您提供对当今世界中确实存在的各种 Web 技术的统一视图。这极大地简化了 Web 应用程序的开发。

我们的下一个任务是创建一个将使用您创建的 Web 服务的客户端。

创建客户端

在服务器应用程序中,HelloWorld是公开我们的 Web 服务的接口。Web 服务本身只是向客户端提供一个简单的问候消息。通常,Web 服务接口使用 WSDL(Web 服务描述语言)向外界公开。在这个简单的应用程序中,我们将通过直接公开服务接口(即HelloWorld.class )向客户端公开我们的 Web 服务。

为此,CXF 提供了一个名为ClientProxyFactoryBean的工厂类,它允许我们将所需的接口附加到创建的工厂实例。

首先,我们创建一个工厂 bean 实例如下 -

<span style="color:#000000">ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
</span>

我们在工厂 bean 实例上调用setAddress方法来设置可以调用我们的 Web 服务的 URL。在我们的例子中,我们将使用在前面的步骤中创建服务器时使用的 URL -

<span style="color:#000000">factory.setAddress("http://localhost:5000/Hello");
</span>

接下来,我们在工厂实例上调用create方法,将我们的服务接口HelloWorld.class附加到它。

<span style="color:#000000">HelloWorld helloServer = factory.create(HelloWorld.class);
</span>

最后,我们调用greetings方法来调用远程 Web 服务。

<span style="color:#000000">System.out.println(helloServer.greetings(System.getProperty("user.name")));
</span>

这将在您的控制台上打印一条问候消息。

客户端应用程序的整个源代码如下所示 -

<span style="color:#000000">//HelloClient.java
package com.tutorialspoint.cxf.pojo;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
public class HelloClient {public static void main(String[] args) throws Exception {ClientProxyFactoryBean factory = new ClientProxyFactoryBean();factory.setAddress("http://localhost:5000/Hello");HelloWorld helloServer = factory.create(HelloWorld.class);System.out.println(helloServer.greetings(System.getProperty("user.name")));}
}
</span>

运行客户端

确保服务器仍在您的计算机上运行。如果超时,请使用以下命令重新启动服务器 -

<span style="color:#000000">mvn -Pserver
</span>

您将在控制台上看到以下消息 -

<span style="color:#000000">Listening on port 5000 ...
</span>

现在,在我们设置为 5 分钟的服务器超时之前,打开另一个命令行窗口并使用以下命令启动客户端 -

<span style="color:#000000">mvn -Pclient
</span>

您将在命令行上看到类似于以下内容的消息 -

<span style="color:#000000">Hi tutorialspoint
</span>

请注意,tutorialspoint是我们的用户名。您将收到带有您自己名字的问候。

在下一章中,我们将学习如何在 JAX-WS(Apache CXF API for XML Web Services)项目中使用 CXF。

带有 JAX-WS 的 Apache CXF

在这个 JAX-WS 应用程序中,我们将使用 Apache CXF-first 方法,就像早期的 POJO 应用程序一样。因此,首先我们将为我们的 Web 服务创建一个接口。

声明服务接口

与前面的例子一样,我们将创建一个简单的服务,它只有一个名为 greetings 的接口方法。服务接口的代码如下所示 -

<span style="color:#000000">//HelloWorld.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.jws.WebService;@WebService
public interface HelloWorld {String greetings(String text);
}
</span>

我们使用@WebService标签对接口进行注释。接下来,我们将实现这个接口。

实现 Web 界面

Web 界面的实现如下所示 -

<span style="color:#000000">//HelloWorldImpl.java
package com.tutorialspoint.cxf.jaxws.helloworld;
public class HelloWorldImpl implements HelloWorld {@Overridepublic String greetings(String name) {return ("hi " + name);}
}
</span>

问候方法使用@Override标记进行注释。该方法向调用者返回一条“hi”消息。

接下来,我们将编写开发服务器的代码。

开发服务器

与 POJO 应用程序不同,我们现在将通过使用 CXF 提供的 Endpoint 类来解耦接口来发布我们的服务。这是在以下两行代码中完成的 -

<span style="color:#000000">HelloWorld implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",implementor,new LoggingFeature()
);
</span>

publish 方法的第一个参数指定了我们的服务将提供给客户端的 URL。第二个参数指定我们服务的实现类。服务器的完整代码如下所示 -

<span style="color:#000000">//Server.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {public static void main(String[] args) throws Exception {HelloWorld implementor = new HelloWorldImpl();Endpoint.publish("http://localhost:9090/HelloServerPort",implementor,new LoggingFeature());System.out.println("Server ready...");Thread.sleep(5 * 60 * 1000);System.out.println("Server exiting ...");System.exit(0);}
}
</span>

要部署我们的服务器,您需要对您的项目进行一些修改,如下所示。

部署服务器

最后,要部署服务器应用程序,您需要在 pom.xml 中再进行一次修改,以将您的应用程序设置为 Web 应用程序。您需要添加到pom.xml 中的代码如下 -

<span style="color:#000000"><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.jaxws.helloworld.Server</mainClass></configuration></execution></executions></plugin></plugins></build></profile>
</profiles>
</span>

在部署应用程序之前,您需要向项目中添加另外两个文件。这些显示在下面的屏幕截图中 -

这些文件是定义CXFServlet映射的 CXF 标准文件。此处显示web.xml文件中的代码供您快速参考 -

<span style="color:#000000">//Web.xml
<?xml version = "1.0" encoding = "UTF-8"??>
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name>cxf</display-name><servlet><description>Apache CXF Endpoint</description><display-name>cxf</display-name><servlet-name>cxf</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>cxf</servlet-name><url-pattern>/services/*</url-pattern></servlet-mapping><session-config><session-timeout>60</session-timeout></session-config>
</web-app>
</span>

cxf-servlet.xml 中,声明服务端点的属性。这显示在下面的代码片段中 -

<span style="color:#000000"><beans ...><jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"id = "helloHTTP"address = "http://localhost:9090/HelloServerPort"serviceName = "helloworld:HelloServiceService"endpointName = "helloworld:HelloServicePort"></jaxws:endpoint>
</beans>
</span>

在这里,我们定义了服务端点的 id、服务可用的地址、服务名称和端点名称。现在,您了解了 CXF servlet 如何路由和处理您的服务。

最后的 pom.xml

pom.xml中包含了一些更依赖。我们没有描述所有依赖项,而是在下面包含了 pom.xml 的最终版本 -

<span style="color:#000000"><?xml version = "1.0" encoding = "UTF-8"??>
<project xmlns = "http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tutorialspoint</groupId><artifactId>cxf-jaxws</artifactId><version>1.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.jaxws.helloworld.Server</mainClass></configuration></execution></executions></plugin></plugins></build></profile><profile><id>client</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal><goals><configuration><mainClass>com.tutorialspoint.cxf.jaxws.helloworld.Client</mainClass></configuration></execution></executions></plugin></plugins></build></profile></profiles><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-features-logging</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies>
</project>
</span>

请注意,它还包括用于构建客户端的配置文件,我们将在本教程的后面部分学习。

运行 HelloWorld 服务

现在,您已准备好运行 Web 应用程序。在命令窗口中,使用以下命令运行构建脚本。

<span style="color:#000000">mvn clean install
</span>
<span style="color:#000000">mvn -Pserver
</span>

您将在控制台上看到以下消息 -

<span style="color:#000000">INFO: Setting the server's publish address to be http://localhost:9090/HelloServerPort
Server ready…
</span>

和之前一样,您可以通过在浏览器中打开服务器 URL 来测试服务器。

由于我们没有指定任何操作,因此我们的应用程序只会向浏览器返回一条错误消息。

现在,尝试将?wsdl添加到您的 URL,您将看到以下输出 -

所以我们的服务器应用程序按预期运行。您可以使用前面描述的Postman等 SOAP 客户端来进一步测试您的服务。

在下一节中,我们将学习如何编写使用我们服务的客户端。

开发客户

在 CXF 应用程序中编写客户端与编写服务器一样简单。这是客户端的完整代码 -

<span style="color:#000000">//Client.java
package com.tutorialspoint.cxf.jaxws.helloworld;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public final class Client {private static final QName SERVICE_NAME= new QName("http://helloworld.jaxws.cxf.tutorialspoint.com/","HelloWorld");private static final QName PORT_NAME= new QName("http://helloworld.jaxws.cxf.tutorialspoint.com/","HelloWorldPort");private Client() {}public static void main(String[] args) throws Exception {Service service = Service.create(SERVICE_NAME);System.out.println("service created");String endpointAddress = "http://localhost:9090/HelloServerPort";service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,endpointAddress);HelloWorld hw = service.getPort(HelloWorld.class);System.out.println(hw.greetings("World"));}
}
</span>

在这里,我们使用 CXF 提供的Service类来绑定到已知服务。我们调用Service类的create方法来获取服务的实例。我们通过调用服务实例的addPort方法来设置已知端口。

现在,我们已准备好使用服务,我们首先通过调用服务实例上的getPort方法来获取服务接口。最后,我们调用我们的greetings方法在控制台上打印问候消息。

现在,由于您已经通过使用 Apache CXF-First 方法学习了 CXF 的基础知识,您现在将在下一章中学习如何将 CXF 与 WSDL-First 方法一起使用。

Apache CXF 与 WSDL 优先

您开发的 CXF-POJO 应用程序导致客户端和服务器之间的耦合非常紧密。直接访问服务接口也可能构成严重的安全威胁。因此,通常需要客户端和服务器之间的解耦,这是通过使用 WSDL(Web 服务描述语言)来实现的。

我们在基于 XML 的 WSDL 文档中编写 Web 服务接口。我们将使用一个工具将此 WSDL 映射到 Apache CXF 接口,然后由我们的客户端和服务器应用程序实现和使用。为了提供解耦,从 WSDL 开始是一种首选方式。为此,您首先需要学习一门新语言——WSDL。编写 WSDL 需要谨慎的方法,如果您在开始工作之前能够对此有所了解,那就更好了。

在本课中,我们将从在 WSDL 文档中定义 Web 服务接口开始。我们将从 WSDL 开始学习如何使用 CXF 创建服务器和客户端应用程序。我们将保持应用程序简单,以保持专注于 CXF 的使用。创建服务器应用程序后,我们将使用内置的 CXF 类将其发布到所需的 URL。

首先,让我们描述一下我们将要使用的 WSDL。

HelloWorld 的 WSDL

我们将要实现的 web 服务将有一个名为greetings的 web 方法,它接受一个包含用户名的字符串参数,并在将问候消息附加到用户名后返回一个字符串消息给调用者。完整的 wsdl 如下所示 -

<span style="color:#000000">//Hello.wsdl
<?xml version = "1.0" encoding = "UTF-8"?>
<wsdl:definitions xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"xmlns:tns = "http://helloworld.tutorialspoint.com/"xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/"xmlns:xsd = "http://www.w3.org/2001/XMLSchema"name = "HelloWorld"targetNamespace = "http://helloworld.tutorialspoint.com/"><wsdl:types><xsd:schema attributeFormDefault = "unqualified"elementFormDefault = "qualified"targetNamespace = "http://helloworld.tutorialspoint.com/"><xsd:element name = "greetings" type = "tns:greetings"/><xsd:complexType name = "greetings"><xsd:sequence><xsd:element minOccurs = "0" name = "arg0" type = "xsd:string"/></xsd:sequence></xsd:complexType><xsd:element name = "greetingsResponse"type = "tns:greetingsResponse"/><xsd:complexType name = "greetingsResponse"><xsd:sequence><xsd:element minOccurs = "0" name = "return" type = "xsd:string"/></xsd:sequence></xsd:complexType></xsd:schema></wsdl:types><wsdl:message name = "greetings"><wsdl:part element = "tns:greetings" name = "parameters"> </wsdl:part></wsdl:message><wsdl:message name = "greetingsResponse"><wsdl:part element = "tns:greetingsResponse" name = "parameters"> </wsdl:part></wsdl:message><wsdl:portType name = "HelloWorldPortType"><wsdl:operation name = "greetings"><wsdl:input message = "tns:greetings" name = "greetings">  </wsdl:input><wsdl:output message = "tns:greetingsResponse" name = "greetingsResponse"></wsdl:output></wsdl:operation></wsdl:portType><wsdl:binding name = "HelloWorldSoapBinding" type = "tns:HelloWorldPortType"><soap:binding style = "document"transport = "http://schemas.xmlsoap.org/soap/http"/><wsdl:operation name = "greetings"><soap:operation soapAction = "" style = "document"/><wsdl:input name = "greetings"></wsdl:input><wsdl:output name = "greetingsResponse"><soap:body use = "literal"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:service name = "HelloWorldService"><wsdl:port binding = "tns:HelloWorldSoapBinding" name = "HelloWorldPort"><soap:address location = "http://localhost:9090/HelloServerPort"/></wsdl:port></wsdl:service>
</wsdl:definitions>
</span>

请注意,编写语法正确的 wsdl 一直是开发人员面临的挑战;有许多工具和在线编辑器可用于创建 wsdl。这些编辑器会询问您要实现的消息名称以及您希望在消息中传递的参数以及您希望客户端应用程序接收的返回消息的类型。如果您了解 wsdl 语法,您可以手动编写整个文档的代码或使用其中一个编辑器来创建您自己的。

在上面的 wsdl 中,我们定义了一个名为greetings 的消息。消息被传递到在http://localhost:9090/HelloServerPort 上运行的名为HelloWorldService的服务

有了这个,我们现在将继续进行服务器开发。在开发服务器之前,我们需要为我们的 Web 服务生成 Apache CXF 接口。这是从给定的 wsdl 中完成的。为此,您使用一个名为wsdl2java的工具。

wsdl2java 插件

由于我们将使用 maven 构建项目,因此您需要将以下插件添加到pom.xml文件中。

<span style="color:#000000"><plugins><plugin><groupId>org.apache.cxf</groupId><artifactId>cxf-codegen-plugin</artifactId><version>3.3.0</version><executions><execution><id>generate-sources</id><phase>generate-sources</phase><configuration><wsdlOptions><wsdlOption><wsdl>src/main/resources/hello.wsdl</wsdl><faultSerialVersionUID> 1 </faultSerialVersionUID></wsdlOption></wsdlOptions></configuration><goals><goal>wsdl2java</goal></goals></execution></executions></plugin>
</plugins>
</span>

请注意,我们将wsdl文件的位置指定为src/main/resources/Hello.wsdl。您必须确保为您的项目创建适当的目录结构,并将前面显示的hello.wsdl文件添加到指定文件夹。

WSDL2Java的插件将编译这个WSDL,并在预先定义的文件夹中创建的Apache CXF类。此处显示了完整的项目结构,供您随时参考。

现在,您已准备好使用wsdl2java生成的类创建服务器。wsdl2java 创建的类如下图所示 -

生成的服务接口

在生成的类列表中,您一定注意到其中之一是 Apache CXF 接口 - 这是HelloWorldPortType.java。在您的代码编辑器中检查此文件。文件内容显示在这里供您随时参考 -

<span style="color:#000000">//HelloWorldPortType.java
package com.tutorialspoint.helloworld;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.3.0
* 2019-02-11T12:05:55.220+05:30
* Generated source version: 3.3.0
*
*/@WebService(targetNamespace = "http://helloworld.tutorialspoint.com/",name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {@WebMethod@RequestWrapper(localName = "greetings", targetNamespace ="http://helloworld.tutorialspoint.com/", className ="com.tutorialspoint.helloworld.Greetings")@ResponseWrapper(localName = "greetingsResponse", targetNamespace ="http://helloworld.tutorialspoint.com/", className ="com.tutorialspoint.helloworld.GreetingsResponse")@WebResult(name = "return", targetNamespace ="http://helloworld.tutorialspoint.com/")public java.lang.String greetings(@WebParam(name = "arg0", targetNamespace ="http://helloworld.tutorialspoint.com/")java.lang.String arg0);
}
</span>

请注意,该接口包含一个名为greetings的方法。这是我们 wsdl 中的消息类型。所述的WSDL2Java工具增加了该方法所生成的界面。现在,您可以理解,无论您在 wsdl 中编写什么消息,都会在接口中生成相应的方法。

现在,您的任务是实现与您在 wsdl 中定义的各种消息相对应的所有这些方法。请注意,在前面的 Apache CXF-First 示例中,我们从 Web 服务的 Apache CXF 接口开始。在这种情况下,Apache CXF 接口是从 wsdl 创建的。

实现服务接口

服务接口的实现是微不足道的。完整的实现如下面的清单所示 -

<span style="color:#000000">//HelloWorldImpl.java
package com.tutorialspoint.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {@Overridepublic String greetings(String name) {return ("hi " + name);}
}
</span>

该代码实现了名为greetings的唯一接口方法。该方法采用一个字符串类型的参数,在其前面添加一个“hi”消息并将结果字符串返回给调用者。

接下来,我们将编写服务器应用程序。

开发服务器

开发服务器应用程序再次变得微不足道。在这里,我们将使用 CXF 提供的Endpoint类来发布我们的服务。这是在以下两行代码中完成的 -

<span style="color:#000000">HelloWorldPortType implementor = new HelloWorldImpl();Endpoint.publish("http://localhost:9090/HelloServerPort",implementor,new LoggingFeature());
</span>

首先,我们创建一个服务实现类的对象——HelloWorldImpl。然后,我们将此引用作为第二个参数传递给发布方法。第一个参数是服务发布到的地址——客户端将使用这个 URL 来访问服务。此处给出了服务器应用程序的完整源代码 -

<span style="color:#000000">//Server.java
package com.tutorialspoint.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {public static void main(String[] args) throws Exception {HelloWorldPortType implementor = new HelloWorldImpl();Endpoint.publish("http://localhost:9090/HelloServerPort",implementor,new LoggingFeature());System.out.println("Server ready...");Thread.sleep(5 * 60 * 1000);System.out.println("Server exiting");System.exit(0);}
}
</span>

要构建此服务器类,您需要在pom.xml 中添加构建配置文件。这如下所示 -

<span style="color:#000000"><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.helloworld.Server</mainClass></configuration></execution></executions></plugin></plugins></build><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies>
</profile>
</span>

请注意,服务器类的完全限定名称在配置中指定。此外,依赖标签指定我们将使用嵌入式 jetty Web 服务器来部署我们的服务器应用程序。

部署服务器

最后,要部署服务器应用程序,您需要在 pom.xml 中再进行一次修改,以将您的应用程序设置为 Web 应用程序。您需要添加到pom.xml 中的代码如下 -

<span style="color:#000000"><defaultGoal>install</defaultGoal>
<pluginManagement><plugins><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version><configuration><webXml>src/main/webapp/WEB-INF/web.xml</webXml><webResources><resource><directory>src/main/resources</directory><targetPath>WEB-INF</targetPath><includes><include>*.wsdl</include></includes></resource></webResources></configuration></plugin></plugins>
</pluginManagement>
</span>

在部署应用程序之前,您需要向项目中添加另外两个文件。这些显示在下面的屏幕截图中 -

这些文件是定义CXFServlet映射的 CXF 标准文件。此处显示web.xml文件中的代码供您快速参考 -

<span style="color:#000000">//cxf-servlet.xml
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version="2.5"xsi:schemaLocation = "http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name>cxf</display-name><servlet><description>Apache CXF Endpoint</description><display-name>cxf</display-name><servlet-name>cxf</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>cxf</servlet-name><url-pattern>/services/*</url-pattern></servlet-mapping><session-config><session-timeout>60</session-timeout></session-config>
</web-app>
</span>

cxf-servlet.xml 中声明服务端点的属性。这显示在下面的代码片段中 -

<span style="color:#000000"><beans ...><jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"id="helloHTTP"address = "http://localhost:9090/HelloServerPort"serviceName = "helloworld:HelloServiceService"endpointName = "helloworld:HelloServicePort"></jaxws:endpoint>
</beans>
</span>

在这里,我们定义了服务端点的 id、服务可用的地址、服务名称和端点名称。现在,您了解了 CXF servlet 如何路由和处理您的服务。

最后的 pom.xml

pom.xml中包含了一些更依赖。我们没有描述所有依赖项,而是在下面包含了 pom.xml 的最终版本 -

<span style="color:#000000"><?xml version="1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tutorialspoint</groupId><artifactId>cxf-wsdl</artifactId><version>1.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><build><defaultGoal>install</defaultGoal><pluginManagement><plugins><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version><configuration><webXml>src/main/webapp/WEB-INF/web.xml</webXml><webResources><resource><directory>src/main/resources</directory><targetPath>WEB-INF</targetPath><includes><include>*.wsdl</include></includes></resource></webResources></configuration></plugin></plugins></pluginManagement><plugins><plugin><groupId>org.apache.cxf</groupId><artifactId>cxf-codegen-plugin</artifactId><version>3.3.0</version><executions><execution><id>generate-sources</id><phase>generate-sources</phase><configuration><wsdlOptions><wsdlOption><wsdl>src/main/resources/Hello.wsdl</wsdl><faultSerialVersionUID>1</faultSerialVersionUID></wsdlOption></wsdlOptions></configuration><goals><goal>wsdl2java</goal></goals></execution></executions></plugin></plugins></build><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.helloworld.Server</mainClass></configuration></execution></executions></plugin></plugins></build><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies></profile><profile><id>client</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.helloworld.Client</mainClass></configuration></execution></executions></plugin></plugins></build></profile></profiles><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-management</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-features-metrics</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf.xjc-utils</groupId><artifactId>cxf-xjc-runtime</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-features-logging</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.8.0-beta2</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies>
</project>
</span>

请注意,它还包括用于构建客户端的配置文件,我们将在后面的部分中很快学习。

运行 HelloWorld 服务

现在,您已准备好运行 Web 应用程序。在命令窗口中,使用以下命令运行构建脚本。

<span style="color:#000000">mvn clean install
</span>

这将从您的 wsdl 生成适当的 Apache CXF 类,编译您的 Apache CXF 类,在嵌入式码头服务器上部署服务器并运行您的应用程序。

您将在控制台上看到以下消息 -

<span style="color:#000000">INFO: Setting the server's publish address to be
http://localhost:9090/HelloServerPort
Server ready...
</span>

和以前一样,您可以通过在浏览器中打开服务器 URL 来测试服务器。

由于我们没有指定任何操作,因此我们的应用程序只会向浏览器返回一条错误消息。现在,尝试将?wsdl添加到您的 URL,您将看到以下输出 -

所以我们的服务器应用程序按预期运行。您可以使用前面描述的Postman等 SOAP 客户端来进一步测试您的服务。

本教程的下一部分是编写一个使用我们服务的客户端。

开发客户

在 CXF 应用程序中编写客户端与编写服务器一样重要。这是客户端的完整代码,基本上只包含三行,其余行只是将服务信息打印给用户。

<span style="color:#000000">//Client.java
package com.tutorialspoint.helloworld;
public class Client {public static void main(String[] args) throws Exception {//Create the service client with its default wsdlurlHelloWorldService helloServiceService = new HelloWorldService();System.out.println("service: " +helloServiceService.getServiceName());System.out.println("wsdl location: " +helloServiceService.getWSDLDocumentLocation());HelloWorldPortType helloService =helloServiceService.getHelloWorldPort();System.out.println(helloService.greetings(System.getProperty("user.name")));}
}
</span>

在这里,我们简单地创建一个我们的服务HelloWorldService的实例,通过调用getHelloWorldPort方法获取它的端口,然后将我们的问候消息传递给它。运行客户端,您将看到以下输出 -

<span style="color:#000000">service: {http://helloworld.tutorialspoint.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang
</span>

到目前为止,您已经了解了如何将 CXF 与 Apache CXF-First 和 WSDL-First 架构一起使用。在 Apache CXF-First 方法中,您使用 POJO 和CXF 库中的ServerFactoryBean类来创建服务器。要创建客户端,您可以使用CXF 库中的ClientProxyFactoryBean类。在 WSDL-First 方法中,您使用Endpoint类在所需的 URL 和指定的实现者处发布服务。您现在可以扩展这些技术以集成不同的协议和传输。

带有 JAX-RS 的 Apache CXF

在继续本章之前,我们假设您知道如何用 Java 编写 RESTful Web 服务。我将向您展示如何在此 JAX-RS(用于 RESTful Web 服务的 Java API)之上使用 CXF。我们将创建一个维护最新电影列表的 Web 服务。当用户请求一部电影时,他在请求中指定了电影ID,服务器将定位该电影并将其返回给客户端。在我们的简单案例中,我们将简单地将电影名称返回给客户端,而不是实际的二进制 MP4 文件。因此,让我们开始创建 JAX-RS 应用程序。

声明电影元素

我们将声明一个名为 Movie 的 XML 根元素,用于存储给定电影的 id 和名称。该元素在名为 Movie.java 的文件中声明。文件的内容显示在这里 -

<span style="color:#000000">//Movie.java
package com.tutorialspoint.cxf.jaxrs.movie;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Movie")
public class Movie {private long id;private String name;public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
</span>

请注意使用XmlRootElement标记为Movie标记声明 XML 元素。接下来,我们将创建一个服务,在其数据库中保存电影列表。

创建电影服务数据库

为了存储电影列表,我们使用 Java 提供的存储键值对的Map。如果列表很大,您将使用更易于管理的外部数据库存储。在我们的简单案例中,我们将仅在数据库中存储五部电影。MovieService 类的代码如下 -

<span style="color:#000000">//MovieService.java
package com.tutorialspoint.cxf.jaxrs.movie;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@Path("/movieservice/")
@Produces("text/xml")
public class MovieService {long currentId = 123;Map<Long, Movie> movies = new HashMap<>();public MovieService() {init();}@GET@Path("/movie/{id}/")public Movie getMovie(@PathParam("id") String id) {long idNumber = Long.parseLong(id);return movies.get(idNumber);}final void init() {Movie c1 = new Movie();c1.setName("Aquaman");c1.setId(1001);movies.put(c1.getId(), c1);Movie c2 = new Movie();c2.setName("Mission Imposssible");c2.setId(1002);movies.put(c2.getId(), c2);Movie c3 = new Movie();c3.setName("Black Panther");c3.setId(1003);movies.put(c3.getId(), c3);Movie c4 = new Movie();c4.setName("A Star is Born");c4.setId(1004);movies.put(c4.getId(), c4);Movie c5 = new Movie();c5.setName("The Meg");c5.setId(1005);movies.put(c5.getId(), c5);}
}
</span>

请注意,我们使用以下两个注释来指定我们的电影服务的 URL 路径及其返回类型 -

<span style="color:#000000">@Path("/movieservice/")
@Produces("text/xml")
</span>

我们使用 @GET 和 @Path 注释来指定 GET 请求的 URL,如下所示 -

<span style="color:#000000">@GET
@Path("/movie/{id}/")
</span>

电影数据库本身是在 init 方法中初始化的,我们在该方法中将五个电影项目添加到数据库中。

我们的下一个任务是编写一个服务器应用程序。

开发服务器

要创建服务器,我们使用 CXF 提供的JAXRSServerFactoryBean类。

<span style="color:#000000">JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
</span>

我们通过调用setResourceClasses方法来设置它的资源类。

<span style="color:#000000">factory.setResourceClasses(Movie.class);
factory.setResourceClasses(MovieService.class);
</span>

我们通过调用setResourceProvider方法来设置服务提供者。

<span style="color:#000000">factory.setResourceProvider(MovieService.class,
new SingletonResourceProvider(new MovieService()));
</span>

我们通过调用aetAddress方法设置所需的发布地址-

<span style="color:#000000">factory.setAddress("http://localhost:9000/");
</span>

最后,我们通过调用工厂实例的 create 方法发布服务器。

<span style="color:#000000">factory.create();
</span>

服务器应用程序的完整代码如下 -

<span style="color:#000000">//Server.java
package com.tutorialspoint.cxf.jaxrs.movie;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
public class Server {public static void main(String[] args) throws Exception {JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();factory.setResourceClasses(Movie.class);factory.setResourceClasses(MovieService.class);  factory.setResourceProvider(MovieService.class,new SingletonResourceProvider(new MovieService()));factory.setAddress("http://localhost:9000/");factory.create();System.out.println("Server ready...");Thread.sleep(5 * 60 * 1000);System.out.println("Server exiting ...");System.exit(0);}
}
</span>

最后的 pom.xml

在这里,我们在下面包含了 pom.xml 的最终版本 -

<span style="color:#000000"><?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tutorialspoint</groupId><artifactId>cxf-jaxrs</artifactId><version>1.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.jaxrs.movie.Server</mainClass></configuration></execution></executions></plugin></plugins></build><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies></profile><profile><id>client</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.cxf.jaxrs.movie.Client</mainClass></configuration></execution></executions></plugin></plugins></build></profile></profiles><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxrs</artifactId><version>3.3.0</version></dependency><dependency><groupId>jakarta.ws.rs</groupId><artifactId>jakarta.ws.rs-api</artifactId><version>2.1.5</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.7</version></dependency></dependencies>
</project>
</span>

开发客户

编写 RS 客户端很简单。我们只需创建一个 URL 对象并打开它的流。我们使用 CXF 提供的 IOUtils 类将输入流的内容复制到本地流。

<span style="color:#000000">URL url = new URL("http://localhost:9000/movieservice/movie/1002");
try (InputStream instream = url.openStream();
CachedOutputStream outstream = new CachedOutputStream()) {IOUtils.copy(instream, outstream);
}
</span>

客户端应用程序的完整代码如下 -

<span style="color:#000000">//Client.java
package com.tutorialspoint.cxf.jaxrs.movie;
import java.io.InputStream;
import java.net.URL;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
public class Client {public static void main(String[] args) throws Exception {URL url = new URL("http://localhost:9000/movieservice/movie/1002");try (InputStream instream = url.openStream();CachedOutputStream outstream = new CachedOutputStream()) {IOUtils.copy(instream, outstream);String str = outstream.getOut().toString();System.out.println(str);}}
}
</span>

测试 JAX-RS 应用程序

在命令行窗口中使用以下命令运行服务器 -

<span style="color:#000000">mvn -Pserver
</span>

现在,您将在控制台上看到以下消息 -

<span style="color:#000000">INFO: Setting the server's publish address to be http://localhost:9000
</span>

现在,打开浏览器并输入以下 URL -

<span style="color:#000000">http://localhost:9000/movieservice/movie/1002
</span>

您将在浏览器窗口中看到以下内容。

您可以使用我们开发的 Java 客户端应用程序调用服务,方法是在单独的命令行窗口中运行以下命令。

<span style="color:#000000">mvn -Pclient
</span>

您将看到以下输出 -

<span style="color:#000000"><?xml version="1.0" encoding = "UTF-8" standalone="yes"?>
<Movie><id>1002</id><name>Mission Imposssible</name></Movie>
</span>

CXF 示例提供了几个关于如何将 CXF 与 JAX-RS 一起使用的示例。鼓励有兴趣的读者研究这些样本。

带有 JMS 的 Apache CXF

如前所述,您可以将 CXF 与 JMS 传输一起使用。在这种情况下,客户端将向已知的 Messaging Server 发送 JMS 消息。我们的服务器应用程序不断地监听消息服务器以获取传入消息。当消息到达时,它处理消息,执行客户端请求并将响应作为另一条消息发送给客户端。

如前所述,我们将首先创建一个示例服务器应用程序,该应用程序提供一个名为sayHi的单一 Web 方法。

创建服务接口

我们的HelloWorld服务的服务接口如下所示 -

<span style="color:#000000">//HelloWorld.java
package com.tutorialspoint.service;import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;@WebService
public interface HelloWorld {@WebMethodString sayHi(@WebParam(name = "name") String name);
}
</span>

实施服务

服务接口的实现定义如下 -

<span style="color:#000000">//HelloWorldImpl.java
package com.tutorialspoint.service.impl;import javax.jws.WebService;
import com.tutorialspoint.service.HelloWorld;@WebService
public class HelloWorldImpl implements HelloWorld {@Overridepublic String sayHi(String name) {return "Hello " + name;}
}
</span>

该实现只是向用户返回一条 Hello 消息。如您所见,该接口及其实现与您迄今为止学习过的本教程中的所有早期项目都相似。

现在,最重要的一点是创建一个服务器应用程序,该应用程序设置一个消息队列并继续监听传入的消息。

创建服务器

在服务器应用程序中,首先我们创建一个JMS端点,如下所示 -

<span style="color:#000000">private static final String JMS_ENDPOINT_URI ="jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"+ "&jndiConnectionFactoryName=ConnectionFactory"+ "&jndiInitialContextFactory"+ "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"+ "&jndiURL = tcp://localhost:61616";
</span>

请注意,我们在指定端口上设置了一个队列,该队列存在指定的时间。我们现在通过实例化org.apache.activemq.broker.BrokerService类来创建消息服务。这是ActiveMQ消息传递服务器的服务器类。

<span style="color:#000000">BrokerService broker = new BrokerService();
</span>

您可以使用除ActiveMQ之外的任何其他消息传递服务器。我们现在将此服务器连接到所需的 URI。

<span style="color:#000000">broker.addConnector("tcp://localhost:61616");
</span>

我们为传入消息的数据存储设置目录 -

<span style="color:#000000">broker.setDataDirectory("target/activemq-data");
</span>

最后,我们使用 start 方法启动服务器 -

<span style="color:#000000">broker.start();
</span>

接下来,我们使用早期 POJO 应用程序中使用的服务器工厂 bean 类创建服务 bean HelloWorld的实例-

<span style="color:#000000">Object implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);
</span>

接下来,我们在工厂上设置 JMS 端点,以便工厂继续监听传入的消息 -

<span style="color:#000000">factory.setTransportId
(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress(JMS_ENDPOINT_URI);
</span>

最后,我们在工厂中设置实现类并开始运行它 -

<span style="color:#000000">factory.setServiceBean(implementor);
factory.create();
</span>

此时您的服务器已启动并正在运行。请注意,由于我们在 POJO 应用程序中使用了工厂 bean 类,因此不需要 CXFServlet 和 web.xml 文件。

完整的服务器应用程序代码显示在这里 -

<span style="color:#000000">//ServerJMS.java
package com.tutorialspoint.server;import java.util.Collections;
import org.apache.cxf.ext.logging.LoggingFeature;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;
import com.tutorialspoint.service.HelloWorld;
import com.tutorialspoint.service.impl.HelloWorldImpl;
import org.apache.activemq.broker.BrokerService;public final class ServerJMS {private static final String JMS_ENDPOINT_URI = "jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"+ "&jndiConnectionFactoryName=ConnectionFactory"+ "&jndiInitialContextFactory"+ "= org.apache.activemq.jndi.ActiveMQInitialContextFactory"+ "&jndiURL = tcp://localhost:61616";public static void main(String[] args) throws Exception {BrokerService broker = new BrokerService();broker.addConnector("tcp://localhost:61616");broker.setDataDirectory("target/activemq-data");broker.start();Object implementor = new HelloWorldImpl();JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();factory.setServiceClass(HelloWorld.class);factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);factory.setAddress(JMS_ENDPOINT_URI);factory.setServiceBean(implementor);factory.setFeatures(Collections.singletonList(new LoggingFeature()));factory.create();System.out.println("Server ready...");Thread.sleep(5 * 60 * 1000);System.out.println("Server exiting");System.exit(0);}
}
</span>

添加依赖项

我们创建的服务器应用程序使用 ActiveMQ 消息传递服务器。因此,您将需要向项目中添加更多的依赖项。此处显示了完整的 pom.xml 文件,以便您了解其他所需的依赖项。

<span style="color:#000000"><?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tutorialspoint</groupId><artifactId>cxf-jms</artifactId><version>1.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><profiles><profile><id>server</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.server.ServerJMS</mainClass></configuration></execution></executions></plugin></plugins></build></profile><profile><id>client</id><build><defaultGoal>test</defaultGoal><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><executions><execution><phase>test</phase><goals><goal>java</goal></goals><configuration><mainClass>com.tutorialspoint.client.ClientJMS</mainClass></configuration></execution></executions></plugin></plugins></build></profile></profiles><dependencies><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-broker</artifactId><version>5.15.8</version></dependency><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-kahadb-store</artifactId><version>5.15.8</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-jms</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-features-logging</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.3.0</version></dependency></dependencies>
</project>
</span>

运行服务器

要开始运行服务器,就像之前的情况一样,在命令窗口中键入以下命令 -

<span style="color:#000000">mvn -Pserver
</span>

这将启动 ActiveMQ 消息服务器,设置消息队列并创建一个持续监听该队列的工厂 bean。

我们的下一个任务是创建一个客户端应用程序。

创建客户端

在客户端应用程序中,首先我们设置与服务器应用程序中使用的相同的 JMS 端点 -

<span style="color:#000000">private static final String JMS_ENDPOINT_URI ="jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"+ "&jndiConnectionFactoryName=ConnectionFactory"+ "&jndiInitialContextFactory"+ " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"+ "&jndiURL = tcp://localhost:61616";
</span>

我们像在 POJO 应用程序中一样创建工厂。

<span style="color:#000000">JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
</span>

我们将端点 URI 和实现者类设置如下 -

<span style="color:#000000">factory.setTransportId (JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setAddress (JMS_ENDPOINT_URI);
HelloWorld client = factory.create(HelloWorld.class);
</span>

最后,我们调用服务方法并打印其结果输出 -

<span style="color:#000000">String reply = client.sayHi("TutorialsPoint");
System.out.println(reply);
</span>

完整的客户端代码如下 -

<span style="color:#000000">// ClientJMS.java
package com.tutorialspoint.client;import com.tutorialspoint.service.HelloWorld;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.jms.spec.JMSSpecConstants;public final class ClientJMS {private static final String JMS_ENDPOINT_URI ="jms:queue:test.cxf.jmstransport.queue?timeToLive=1000"+ "&jndiConnectionFactoryName=ConnectionFactory"+ "&jndiInitialContextFactory"+ " = org.apache.activemq.jndi.ActiveMQInitialContextFactory"+ "&jndiURL = tcp://localhost:61616";public static void main(String[] args) throws Exception {JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);factory.setAddress(JMS_ENDPOINT_URI);HelloWorld client = factory.create(HelloWorld.class);String reply = client.sayHi("TutorialsPoint");System.out.println(reply);System.exit(0);}
}
</span>

Apache CXF - 结论

CXF 提供了一种统一的方法来混合匹配当今世界中存在的用于创建 Web 应用程序的多种 Web 协议和传输。您学习了如何从传统的 Java 界面开始创建使用 CXF 的 Web 应用程序。接下来,您学习了如何从 WSDL 开始创建 Web 应用程序及其客户端。

WSDL 提供服务接口的 XML 表示。您使用 wsdl2java 工具从 WSDL 创建 Java 接口,最后使用创建的接口编写服务器和客户端。本教程还简要介绍了在 RESTful Web 服务应用程序中使用 CXF。最后,我们还讨论了如何将 CXF 与 JMS 一起使用。您现在可以参考CXF 样本进行进一步研究。

注意- 整个项目源代码可以从这里下载。

Apache CXF - 快速指南相关推荐

  1. gr java ch,Apache POI 快速指南.pdf

    Apache POI PPT - 快速指南 Apache POI PPT - 概述 很多时候,需要⼀个软件应⽤程序来⽣成Microsoft Office⽂件格式的报告. 有时,应 ⽤程序甚⾄希望接 M ...

  2. Apache PDFbox快速开发指南

    Apache PDFbox快速开发指南 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.介绍 Apache PDFbox是一个开源的.基于Java的. ...

  3. 使用Apache cxf 和Spring在Tomcat下发布Webservice指南

    转载 http://blog.csdn.net/zhangzhaokun/article/details/4750021 最近学习了如何使用apache cxf和Spring发布webservice, ...

  4. jetty嵌入式容器_嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务

    jetty嵌入式容器 最近,我遇到了一个非常有趣的问题,我认为这只需要几分钟就可以解决:在Linux中使用Spring Security (当前稳定版本3.2.5 )保护Apache CXF (当前版 ...

  5. 嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务

    最近,我遇到了一个非常有趣的问题,我认为这只花了我几分钟就解决了:在Windows Server 2003中使用Spring Security (当前稳定版本3.2.5 )保护Apache CXF ( ...

  6. 架构设计:系统间通信(36)——Apache Camel快速入门(上)

    1.本专题主旨 1-1.关于技术组件 在这个专题中,我们介绍了相当数量技术组件:Flume.Kafka.ActiveMQ.Rabbitmq.Zookeeper.Thrift .Netty.DUBBO等 ...

  7. 闻与MyBatis之MyBatis快速指南

    本文内容如有错误.不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢.欢迎转载,转载请注明出处(https://blog.csdn.net/feng_xiaoshi/article/det ...

  8. Apache CXF 简介

    Apache CXF 简介 开放源代码的服务框架 本教程介绍了 Apache CXF 服务框架的基本知识,并通过讲解自带的例子来初步体验通过 CXF 进行服务的发布与消费:然后搭建基于 Eclipse ...

  9. Apache CXF 介绍

    Apache CXF 简介 关于Apache CXF Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 A ...

最新文章

  1. OpenCV读写xml和yml文件
  2. Centos Ftp
  3. mysql如何建立索引workbench_如何对MySQL索引进行优化分析
  4. 视频 + PPT | 突破“十面埋伏”,银行业玩转数字化运营
  5. Oracle中删除用户和表空间的常见问题(比如:ORA-01940无法删除当前已连接用户的解决方案)
  6. 属性编辑器未在PropertyEditorManager中注册?
  7. 小案例:搭建简易版王者荣耀英雄购买商城网页版
  8. plsql删除大量数据_一次oracle大量数据删除经历
  9. iis7.5 php 404.17,部署IISHTTP 404.17无法由静态文件处理程序来处理
  10. asp.net控件开发基础二
  11. 录音转文字 android,录音转文字pro
  12. 湖州市技师学院的计算机,湖州技师学院
  13. Openjudge 1.13 33:实数加法
  14. Hadoop2.7.1+Hbase1.2.1集群环境搭建(3)1.x和2.x都支持的集群安装方式
  15. java的视频案例教学 值得下载
  16. vue实现消息badge 标记_vue 新消息提示
  17. 发展战略-以技术为导向还是以产品为导向的方向选择?
  18. Clipboard.js移动端【ios】复制事件不生效解决方法
  19. opencv 基于sift的多张图片全景图拼接
  20. vue 雷达扫描_Groundvue系列地质雷达探测系统及其应用

热门文章

  1. (决策树,朴素贝叶斯,人工神经网络)实现鸢尾花数据集分类
  2. alertmanager实现邮件告警以及设置告警主题
  3. C++实现多项式拟合
  4. 4. TabBar,ScrollBar,ProgressBar,MenuBar,ToolBar
  5. 重定向转发,接收请求参数及数据回显-P11,12
  6. 3,Verilog中数值的表示
  7. 广州穗雅医院[口腔黏膜病]导致口腔扁平苔藓原因有哪些?
  8. 关于eclipse出现The superclass “javax.servlet.http.HttpServlet“ was not found on the Java Build Path问题
  9. 使用compression中间件压缩响应数据
  10. R软件学习笔记—Legend