Apache CXF 與 JAX-RS



在繼續本章之前,我們假設您知道如何用 Java 編寫 RESTful 網路服務。我將向您展示如何在 JAX-RS(Java API for RESTful Web Services)之上使用 CXF。我們將建立一個維護最新電影列表的 Web 服務。當用戶請求一部電影時,他在請求中指定電影 ID,伺服器將找到該電影並將其返回給客戶端。在我們的簡單示例中,我們將只向客戶端返回電影名稱,而不是實際的二進位制 MP4 檔案。所以讓我們開始建立 JAX-RS 應用程式。

宣告電影元素

我們將宣告一個名為 Movie 的 XML 根元素,用於儲存給定電影的 ID 和名稱。該元素在名為 Movie.java 的檔案中宣告。檔案內容如下所示:

//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;
   }
}

注意使用XmlRootElement標籤宣告Movie標籤的 XML 元素。接下來,我們將建立一個服務,在其資料庫中儲存電影列表。

建立電影服務資料庫

為了儲存電影列表,我們使用 Java 提供的Map來儲存鍵值對。如果列表很大,您可以使用外部資料庫儲存,這也很容易管理。在我們的簡單示例中,我們只在資料庫中儲存五部電影。MovieService 類的程式碼如下:

//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);
   }
}

請注意,我們使用以下兩個註解來指定電影服務的 URL 路徑及其返回型別:

@Path("/movieservice/")
@Produces("text/xml")

我們使用 @GET 和 @Path 註解來指定 GET 請求的 URL,如下所示:

@GET
@Path("/movie/{id}/")

電影資料庫本身在 init 方法中初始化,我們向資料庫中添加了五部電影。

我們的下一個任務是編寫一個伺服器應用程式。

開發伺服器

為了建立一個伺服器,我們使用 CXF 提供的JAXRSServerFactoryBean類。

JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();

我們透過呼叫setResourceClasses方法設定其資源類。

factory.setResourceClasses(Movie.class);
factory.setResourceClasses(MovieService.class);

我們透過呼叫setResourceProvider方法設定服務提供商。

factory.setResourceProvider(MovieService.class,
new SingletonResourceProvider(new MovieService()));

我們透過呼叫setAddress方法設定所需的釋出地址:

factory.setAddress("https://:9000/");

最後,我們透過呼叫factory例項上的 create 方法來發布伺服器。

factory.create();

伺服器應用程式的完整程式碼如下:

//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("https://:9000/");
      factory.create();
      
      System.out.println("Server ready...");
      Thread.sleep(5 * 60 * 1000);
      
      System.out.println("Server exiting ...");
      System.exit(0);
   }
}

最終的 pom.xml

這裡我們包含了最終版本的 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-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>

開發客戶端

編寫 RS 客戶端很簡單。我們只需建立一個 URL 物件並開啟其流。我們使用 CXF 提供的 IOUtils 類將輸入流的內容複製到本地流。

URL url = new URL("https://:9000/movieservice/movie/1002");
try (InputStream instream = url.openStream();
CachedOutputStream outstream = new CachedOutputStream()) {
   IOUtils.copy(instream, outstream);
}

客戶端應用程式的完整程式碼如下:

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

測試 JAX-RS 應用程式

在命令列視窗中使用以下命令執行伺服器:

mvn -Pserver

現在,您將在控制檯中看到以下訊息:

INFO: Setting the server's publish address to be https://:9000

現在,開啟您的瀏覽器並輸入以下 URL:

https://:9000/movieservice/movie/1002

您將在瀏覽器視窗中看到以下內容。

browser window

您可以透過使用我們開發的 Java 客戶端應用程式來呼叫服務,在單獨的命令列視窗中執行以下命令。

mvn -Pclient

您將看到以下輸出:

<?xml version="1.0" encoding = "UTF-8" standalone="yes"?>
<Movie><id>1002</id><name>Mission Imposssible</name></Movie>

CXF 示例提供了許多關於如何使用 CXF 與 JAX-RS 的示例。鼓勵感興趣的讀者學習這些示例。

廣告
© . All rights reserved.