Java 中的 Restful Web Services 教程

歡迎來到Java的Restful Web服務教程。REST是代表狀態轉換(REpresentational State Transfer)的首字母縮寫。REST是一種用於開發可通過網絡訪問的應用程序的架構風格。REST架構風格是由羅伊·費爾丁在他於2000年的博士論文中提出的。

Restful Web服務

Restful Web服務是一種無狀態的客戶端-服務器架構,其中Web服務是資源,可以通過其URI進行識別。REST客戶端應用程序可以使用HTTP GET/POST方法來調用Restful Web服務。REST不指定任何特定的協議來使用,但在幾乎所有情況下都是使用HTTP/HTTPS。與SOAP Web服務相比,這些服務輕量級,並且不遵循任何標準。我們可以使用XML、JSON、文本或任何其他類型的數據進行請求和響應。

Java RESTful Web服務API

Java API for RESTful Web Services (JAX-RS)是用於創建REST Web服務的Java API。JAX-RS使用註釋來簡化Web服務的開發和部署。JAX-RS是JDK的一部分,因此您無需包含任何內容來使用其註釋。

Restful Web Services Annotations

一些重要的 JAX-RS 注解包括:

  • @Path:用於指定類和方法的相對路徑。通過掃描 Path 注解值,我們可以獲得 Web 服務的 URI。
  • @GET@PUT@POST@DELETE@HEAD:用於指定方法的 HTTP 請求類型。
  • @Produces@Consumes:用於指定請求和響應類型。
  • @PathParam:用於通過解析將方法參數綁定到路徑值。

Restful Web Services and SOAP

  1. SOAP 是一種協議,而 REST 是一種架構風格。
  2. SOAP 服務器和客戶端應用程序緊密耦合並與 WSDL 合同綁定,而 REST Web 服務和客戶端則沒有合同。
  3. 與 SOAP Web 服務相比,REST Web 服務的學習曲線更容易。
  4. REST Web 服務的請求和響應類型可以是 XML、JSON、文本等,而 SOAP 僅使用 XML。
  5. JAX-RS 是用於 REST web 服務的 Java API,而 JAX-WS 是用於 SOAP web 服務的 Java API。

REST API 實現

有兩個主要的 JAX-RS API 實現。

  1. Jersey: Jersey 是 Sun 提供的參考實現。要將 Jersey 用作我們的 JAX-RS 實現,我們只需在 web.xml 中配置其 servlet 並添加所需的依賴項。請注意,JAX-RS API 是 JDK 的一部分,而不是 Jersey,因此我們必須在應用程序中添加其依賴項 jars。
  2. RESTEasy: RESTEasy 是提供 JAX-RS 實現的 JBoss 項目。

Java Restful Web Services 教程

讓我們看看使用 Jersey 和 RESTEasy 創建 Restful web 服務有多簡單。我們將在 HTTP 上公開以下方法,並使用 Chrome Postman 擴展來測試這些方法。

URI HTTP Method Description
/person/{id}/getDummy GET Returns a dummy person object
/person/add POST Adds a person
/person/{id}/delete GET Delete the person with ‘id’ in the URI
/person/getAll GET Get all persons
/person/{id}/get GET Get the person with ‘id’ in the URI

Jersey Restful Web Services

建立動態 Web 專案,然後將其轉換為 Maven,以獲取 Web 服務專案的框架。下圖顯示最終專案的項目結構。 讓我們來看看 pom.xml 檔案中我們擁有的 Jersey 依賴項。

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>JAXRS-Example</groupId>
  <artifactId>JAXRS-Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.19</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.19</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.19</version>
        </dependency>
  </dependencies>
  
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

我們不需要添加 jersey-client 依賴項,但如果您正在編寫 Java 程式來調用使用 Jersey 的 REST Web 服務,則需要它。現在讓我們來看看部署描述符,以了解如何配置 Jersey 來建立我們的 Web 應用程式。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>JAXRS-Example</display-name>

<!-- Jersey Servlet configurations -->
    <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.journaldev</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
  <!-- Jersey Servlet configurations -->

</web-app>

這就是將 Jersey 插入到我們的 Web 應用程式中所需的全部,在我們的 Java 程式碼中,我們將使用 JAX-RS 標註。請注意初始參數 com.sun.jersey.config.property.packages 的值,以提供將被掃描以尋找 Web 服務資源和方法的套件。

REST 範例模型類別

首先,我們將創建兩個模型 Bean – Person 用於我們的應用程式資料和 Response 用於向客戶端系統發送響應。由於我們將發送 XML 響應,因此 Bean 應該被標註為 @XmlRootElement,因此我們有這個類別。

package com.journaldev.jaxrs.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement (name="person")
public class Person {
	private String name;
	private int age;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
	@Override
	public String toString(){
		return id+"::"+name+"::"+age;
	}

}
package com.journaldev.jaxrs.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Response {

	private boolean status;
	private String message;

	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}

REST Web Services 教程服務

根據我們的URI結構,以下是服務接口及其實現代碼。

package com.journaldev.jaxrs.service;

import com.journaldev.jaxrs.model.Person;
import com.journaldev.jaxrs.model.Response;

public interface PersonService {

	public Response addPerson(Person p);
	
	public Response deletePerson(int id);
	
	public Person getPerson(int id);
	
	public Person[] getAllPersons();

}
package com.journaldev.jaxrs.service;


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.journaldev.jaxrs.model.Person;
import com.journaldev.jaxrs.model.Response;

@Path("/person")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class PersonServiceImpl implements PersonService {

	private static Map<Integer,Person> persons = new HashMap<Integer,Person>();
	
	@Override
	@POST
    @Path("/add")
	public Response addPerson(Person p) {
		Response response = new Response();
		if(persons.get(p.getId()) != null){
			response.setStatus(false);
			response.setMessage("Person Already Exists");
			return response;
		}
		persons.put(p.getId(), p);
		response.setStatus(true);
		response.setMessage("Person created successfully");
		return response;
	}

	@Override
	@GET
    @Path("/{id}/delete")
	public Response deletePerson(@PathParam("id") int id) {
		Response response = new Response();
		if(persons.get(id) == null){
			response.setStatus(false);
			response.setMessage("Person Doesn't Exists");
			return response;
		}
		persons.remove(id);
		response.setStatus(true);
		response.setMessage("Person deleted successfully");
		return response;
	}

	@Override
	@GET
	@Path("/{id}/get")
	public Person getPerson(@PathParam("id") int id) {
		return persons.get(id);
	}
	
	@GET
	@Path("/{id}/getDummy")
	public Person getDummyPerson(@PathParam("id") int id) {
		Person p = new Person();
		p.setAge(99);
		p.setName("Dummy");
		p.setId(id);
		return p;
	}

	@Override
	@GET
	@Path("/getAll")
	public Person[] getAllPersons() {
		Set<Integer> ids = persons.keySet();
		Person[] p = new Person[ids.size()];
		int i=0;
		for(Integer id : ids){
			p[i] = persons.get(id);
			i++;
		}
		return p;
	}

}

大部分代碼都是自解釋的,花點時間熟悉 JAX-RS 注釋 @Path@PathParam@POST@GET@Consumes@Produces

Restful Web Services 測試

就是這樣。我們的 Web 服務已經準備就緒,只需將其導出為 WAR 檔案並放入 Tomcat webapps 目錄,或部署到您選擇的任何其他容器中。以下是使用 Postman Chrome 擴展為此 Web 服務執行的一些測試。請注意,在下面的圖像中,我們必須在請求標頭中提供 Accept 和 Content-Type 值為“application/xml”。

  • getDummy
  • 新增
  • 獲取
  • 獲取全部
  • 刪除

這就是使用Jersey JAX-RS實現Web服務的所有內容。如您所見,大部分代碼都使用了JAX-RS標註,Jersey是通過部署描述符和依賴插入的。

RESTEasy RESTful Web Services Example

我們將使用在Jersey專案中開發的所有業務邏輯,但不是對同一專案進行更改,我已經創建了一個新專案。創建一個動態Web專案並將其轉換為Maven專案。然後複製所有Java類 – Person、Response、PersonService和PersonServiceImpl。以下是在完成所有更改後的最終專案。在pom.xml文件中添加以下RESTEasy依賴項。

<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jaxrs</artifactId>
	<version>3.0.13.Final</version>
</dependency>
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jaxb-provider</artifactId>
	<version>3.0.13.Final</version>
</dependency>

以下是我們正在配置Resteasy servlet的web.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>JAXRS-Example-RestEasy</display-name>
     
    <listener>
      <listener-class>
         org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
      </listener-class>
   	</listener>
   
    <servlet>
        <servlet-name>resteasy-servlet</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
        </servlet-class>
        <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.journaldev.jaxrs.resteasy.app.MyApp</param-value>
    </init-param>
    </servlet>
  
    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
	
</web-app>

請注意,我們在init-param中提供了`MyApp`類作為值,在這裡我們擴展了`javax.ws.rs.core.Application`類,如下所示。

package com.journaldev.jaxrs.resteasy.app;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.core.Application;

import com.journaldev.jaxrs.service.PersonServiceImpl;

public class MyApp extends Application {
	
	private Set<Object> singletons = new HashSet<Object>();

	public MyApp() {
		singletons.add(new PersonServiceImpl());
	}

	@Override
	public Set<Object> getSingletons() {
		return singletons;
	}

}

RESTEasy Web Services Test

就是這樣。我們的Web服務已經準備好使用RESTEasy JAX-RS實現。以下是一些來自Postman Chrome擴展測試的輸出。

  • getDummy
  • 添加
  • 獲取

這就是關於Restful Web Services 教程的所有內容,我希望你了解了 JAX-RS 標註的重要性,並明白了擁有標準 API 的好處,這有助於我們重用代碼,並輕鬆從 Jersey 轉移到 RESTEasy。

Source:
https://www.digitalocean.com/community/tutorials/restful-web-services-tutorial-java