Apache CXF 与 POJO



在本节中,您将学习如何开发一个简单的 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 方法。该方法采用string类型的参数,我们将在其中发送用户的姓名。该服务将向调用方发送一条问候消息,其中包含接收到的用户名。

Web 服务接口

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

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

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

Web 服务实现

HelloWorld接口在HelloWorldImpl Apache CXF 类中实现,如下所示:

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

greetings方法接收一个string类型的参数,将其追加到问候消息中,并将结果字符串返回给调用方。

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

创建服务器

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

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

  • 第二部分编写一个main方法来实例化它。

服务器使用 CXF 库提供的ServerFactoryBean类将我们的HelloWorld接口暴露给远程客户端。因此,我们首先实例化ServerFactoryBean类,然后设置其各种属性:

ServerFactoryBean factory = new ServerFactoryBean();

我们通过在factory对象上调用setServiceClass方法来设置要调用的服务类:

factory.setServiceClass(HelloWorld.class);

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

factory.setAddress("https://127.0.0.1:5000/Hello");

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

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

factory.setServiceBean(new HelloWorldImpl());

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

factory.create();

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

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

public static void main(String[] args) throws Exception {
   new HelloServer();
   System.out.println("Listening on port 5000 ...");
}

一旦实例化,HelloServer类将无限期运行。对于生产部署,您肯定希望服务器永远运行。在当前情况下,我们将以如下方式在预定时间后终止服务器:

Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting ...");
System.exit(0);

HelloServer类的完整代码如下所示:

//HelloServer.java
//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("https://127.0.0.1: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);
   }
}

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

设置 Maven 项目

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

mvn archetype:generate

当系统提示输入属性时,输入以下值:

Define value for property 'groupId': : com.tutorialspoint
Define value for property 'artifactId': : cxf-pojo
Define value for property 'version': 1.0-SNAPSHOT: : 1.0
Define value for property 'package': com.tutorialspoint: : com.tutorialspoint.cxf.pojo

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

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

Directory Structure

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

<?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>

上面的 pom.xml 可能包含与本项目无关的其他依赖项,但对于本教程中的下一个项目是必需的。无论如何,包含其他依赖项本身并无害处。

项目文件夹结构

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

Project Folder Structure

运行服务器

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

mvn clean install

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

mvn -Pserver

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

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 https://127.0.0.1:5000/Hello
Listening on port 5000 ...

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

Output Document Tree

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

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

输出如下所示:

Running Server Output

请注意,SOAP 请求是手动编码的。发布请求后,服务器发送了SOAP 响应消息,这在屏幕截图的底部部分可见。

由此,您可以了解到 CXF 在维护请求和响应都使用 SOAP 协议的同时,为您提供了一个统一的视图来查看当今世界存在的各种 Web 技术。这极大地简化了 Web 应用程序的开发。

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

创建客户端

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

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

首先,我们如下创建工厂 bean 实例:

ClientProxyFactoryBean factory = new ClientProxyFactoryBean();

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

factory.setAddress("https://127.0.0.1:5000/Hello");

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

HelloWorld helloServer = factory.create(HelloWorld.class);

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

System.out.println(helloServer.greetings(System.getProperty("user.name")));

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

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

//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("https://127.0.0.1:5000/Hello");
      HelloWorld helloServer = factory.create(HelloWorld.class);
      System.out.println(helloServer.greetings(System.getProperty("user.name")));
   }
}

运行客户端

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

mvn -Pserver

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

Listening on port 5000 ...

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

mvn -Pclient

您将在命令行上看到类似以下的消息:

Hi tutorialspoint

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

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

广告