Apache CXF với JAX-RS

Trước khi tiếp tục chương này, chúng tôi giả định rằng bạn biết cách viết một dịch vụ web RESTful bằng Java. Tôi sẽ chỉ cho bạn cách sử dụng CXF trên JAX-RS này (API Java cho Dịch vụ Web RESTful). Chúng tôi sẽ tạo một dịch vụ web lưu trữ danh sách các bộ phim mới nhất. Khi người dùng yêu cầu một bộ phim, anh ta chỉ định ID phim trong yêu cầu của mình, máy chủ sẽ xác định vị trí phim và trả lại cho máy khách. Trong trường hợp nhỏ của chúng tôi, chúng tôi sẽ chỉ trả lại tên phim cho máy khách chứ không phải tệp MP4 nhị phân thực tế. Vì vậy, chúng ta hãy bắt đầu tạo một ứng dụng JAX-RS.

Khai báo yếu tố phim

Chúng tôi sẽ khai báo một phần tử gốc XML có tên là Movie để lưu trữ id và tên của một bộ phim nhất định. Phần tử được khai báo trong tệp có tên Movie.java. Nội dung của tệp được hiển thị ở đây -

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

Lưu ý việc sử dụng XmlRootElement để khai báo phần tử XML cho Movienhãn. Tiếp theo, chúng ta sẽ tạo một dịch vụ lưu danh sách phim trong cơ sở dữ liệu của nó.

Tạo cơ sở dữ liệu dịch vụ phim

Để lưu danh sách phim, chúng tôi sử dụng Java được cung cấp Maplưu trữ các cặp khóa-giá trị. Nếu danh sách lớn, bạn sẽ sử dụng bộ lưu trữ cơ sở dữ liệu bên ngoài, điều này cũng sẽ dễ quản lý hơn. Trong trường hợp nhỏ của chúng tôi, chúng tôi sẽ chỉ lưu trữ năm phim trong cơ sở dữ liệu của mình. Mã cho lớp MovieService được cung cấp bên dưới:

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

Lưu ý rằng chúng tôi sử dụng hai chú thích sau để chỉ định đường dẫn URL cho dịch vụ phim của chúng tôi và kiểu trả về của nó -

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

Chúng tôi sử dụng chú thích @GET và @Path để chỉ định URL cho yêu cầu GET như sau:

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

Bản thân cơ sở dữ liệu phim được khởi tạo trong phương thức init, nơi chúng tôi thêm năm mục phim vào cơ sở dữ liệu.

Nhiệm vụ tiếp theo của chúng ta là viết một ứng dụng máy chủ.

Máy chủ đang phát triển

Để tạo một máy chủ, chúng tôi sử dụng CXF được cung cấp JAXRSServerFactoryBean lớp học.

JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();

Chúng tôi đặt các lớp tài nguyên của nó bằng cách gọi setResourceClasses phương pháp.

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

Chúng tôi đặt nhà cung cấp dịch vụ bằng cách gọi đến setResourceProvider phương pháp.

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

Chúng tôi đặt mong muốn publish địa chỉ bằng cách gọi aetAddress phương pháp -

factory.setAddress("http://localhost:9000/");

Cuối cùng, chúng tôi xuất bản máy chủ bằng cách gọi phương thức tạo trên factory ví dụ.

factory.create();

Toàn bộ mã cho ứng dụng máy chủ được cung cấp bên dưới:

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

Pom.xml cuối cùng

Ở đây chúng tôi đã bao gồm phiên bản cuối cùng của pom.xml bên dưới -

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

Đang phát triển khách hàng

Viết RS client là một việc tầm thường. Chúng tôi chỉ cần tạo một đối tượng URL và mở luồng của nó. Chúng tôi sử dụng lớp IOUtils do CXF cung cấp để sao chép nội dung của luồng đầu vào vào luồng cục bộ.

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

Toàn bộ mã cho ứng dụng khách được cung cấp bên dưới:

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

Thử nghiệm ứng dụng JAX-RS

Chạy máy chủ bằng lệnh sau trong cửa sổ dòng lệnh:

mvn -Pserver

Bây giờ, bạn sẽ thấy thông báo sau trên bảng điều khiển -

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

Bây giờ, hãy mở trình duyệt của bạn và nhập URL sau:

http://localhost:9000/movieservice/movie/1002

Bạn sẽ thấy thông tin sau trong cửa sổ trình duyệt.

Bạn có thể gọi dịch vụ bằng cách sử dụng ứng dụng khách Java mà chúng tôi đã phát triển bằng cách chạy lệnh sau trong một cửa sổ dòng lệnh riêng biệt.

mvn -Pclient

Bạn sẽ thấy kết quả sau:

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

Các mẫu CXF cung cấp một số ví dụ về cách sử dụng CXF với JAX-RS. Các độc giả quan tâm được khuyến khích nghiên cứu các mẫu này.