Cloud Endpoints Frameworks 註解和語法

Endpoints Frameworks 註解說明 API 設定、方法、參數,以及其他定義端點屬性與行為的重要詳細資料。

如要瞭解如何使用 Maven 專案來加上註解,請參閱「編寫程式碼並加上註解」。我們提供 Maven App Engine Cloud Endpoints 成品,讓您能夠建構後端 API,並藉由後端 API 產生用戶端程式庫。

@Api 註解可以指定整個 API 的設定與行為 (影響 API 內所有公開類別及其公開方法)。「在類別中加上 @Api 註解的所有公開、非靜態、非橋接方法,都會在公開 API 中公開。」

如果您需為特定方法搭配特殊的 API 設定,則可以視需要使用 @ApiMethod 為個別方法進行設定。您可以透過各種屬性設定這些註解,如下方表格所示。

@Api: API-scoped annotations

除非使用 @ApiMethod 加以覆寫,否則 @Api 註解會設定整個 API,並且會套用到類別的所有公開方法。

如要覆寫 API 中特定類別的某個 @Api 註解,請參閱 @ApiClass@ApiReference

必要匯入項目

如要使用這項功能,您必須匯入以下內容:

import com.google.api.server.spi.config.Api;

屬性

@Api 屬性 說明 範例
audiences 如果 API 需要驗證,以及如果您支援 Android 用戶端,則為必要屬性。詳情請參閱用戶端 ID 和目標對象一節。 audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
apiKeyRequired 選用屬性。用於限制存取提供 API 金鑰的要求。 apiKeyRequired = AnnotationBoolean.TRUE
authenticators 如果 API 驗證使用 Firebase、Auth0 或服務帳戶,則為必要屬性。如果您的 API 是使用 Google ID 憑證來進行驗證,就不需要設定這個屬性。您可以在 API 層級或個別方法層級設定這個屬性。您可以將它設為 {EspAuthenticator.class},或編寫自己的自訂驗證器,如 Interface Authenticator 頁面說明。 authenticators = {EspAuthenticator.class}
backendRoot 已淘汰,如要透過不同的路徑提供 API,請在 web.xml 檔案中,變更 EndpointsServlet 部分中的 url-pattern <url-pattern>/example-api/*</url-pattern>
canonicalName 用於為用戶端程式庫中的 API 指定不同或較易解讀的名稱。這個名稱會用來產生用戶端程式庫中的名稱;而後端 API 會繼續使用 name 屬性中指定的值。

例如,如果將 API 的 name 設為 dfaanalytics,您就可以使用這個屬性來指定 DFA Group Analytics 的正式名稱;隨後產生的用戶端類別則會包含名稱DfaGroupAnalytics

您應該在名稱之間包含相關空格,這些空格都會替換為適用的駝峰式大小寫或底線。
canonicalName = "DFA Analytics:"
clientIds 如果您的 API 使用了驗證機制,就必須設定這個屬性。針對可以要求憑證的用戶端,列出用戶端 ID 清單。詳情請參閱用戶端 ID 和目標對象一節。 clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
defaultVersion 指定如果 version 屬性中未提供版本時,系統是否使用預設版本。 defaultVersion = AnnotationBoolean.TRUE
description API 的簡短說明,會公開顯示在探索服務中,以便使用者瞭解您的 API,也能視需要用於產生說明文件。 description = "Sample API for a simple game"
documentationLink 方便使用者找到這個 API 版本說明文件的網址。此網址會出現在 API Explorer 頁面頂端醒目顯示的「瞭解詳情」,讓使用者進一步瞭解您的服務。 documentationLink = "http://link_to/docs"
issuers 自訂 JWT 核發者設定。 issuers = { @ApiIssuer(name = "auth0", issuer = "https://test.auth0.com/authorize", jwksUri = "https://test.auth0.com/.well-known/jwks.json") }
issuerAudiences 個別核發者的目標對象。 issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
limitDefinitions (選用步驟) 用來為 API 定義配額,請參閱 @ApiLimitMetric limitDefinitions = { @ApiLimitMetric(name = "read-requests", displayName = "Read requests", limit = 1000)}
name API 的名稱,用於做為所有 API 方法和路徑的前置字串。name 值:
  • 「必須」以小寫字母開頭
  • 「必須」[a-z]+[A-Za-z0-9]* 規則運算式相符
如果您未指定 name,系統會使用預設的 myapi
name = "foosBall"
namespace 為產生的用戶端設定命名空間,請參閱 @ApiNamespace namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform")
root 已淘汰,如要透過不同的路徑提供 API,請在 web.xml 檔案中,變更 EndpointsServlet 部分中的 url-pattern <url-pattern>/example-api/*</url-pattern>
scopes 如果沒有提供,則預設值是電子郵件範圍 (https://www.googleapis.com/auth/userinfo.email)。使用 OAuth 驗證機制時,一定要指定範圍。如果需要,您可以加以覆寫,以指定更多 OAuth 2.0 範圍。但是請注意,若您定義了多個範圍,而憑證是針對「任何」指定的範圍所新建,則會通過範圍檢查。如需多個範圍,則應指定單一 String,每個範圍之間使用一個半形空格分隔。如要覆寫這裡為特定 API 方法指定的範圍,請在 @ApiMethod 註解中指定不同的範圍。 scopes = {"ss0", "ss1 and_ss2"}
title 在 API Explorer 中顯示為 API 標題的文字,並於探索及目錄服務中公開。 title = "My Backend API"
transformers 指定自訂轉換器的清單。請注意,系統提供了建議使用的替代註解 (@ApiTransformer)。這個屬性已經由 @ApiTransformer 覆寫。 transformers = {BazTransformer.class}
version 指定您的 Endpoint 版本。如果您未提供這個選項,系統會使用預設的 v1 version = "v2"

範例 @Api 註解

這個註解置於類別定義之前:

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

用戶端 ID 和目標對象

針對 OAuth2 驗證,特定用戶端 ID 會獲派 OAuth2 憑證,即代表您可以使用用戶端 ID 限制他人存取您的 API。當您在 Google Cloud 控制台中註冊 Android 應用程式時,就等同為該應用程式建立用戶端 ID。這個用戶端 ID 會從 Google 要求提供 OAuth2 憑證以進行驗證。當後端 API 受驗證保護時,Endpoints 會傳送並開啟 OAuth2 存取憑證,系統會從憑證中擷取用戶端 ID,然後比較 ID 與後端宣告的可接受用戶端 ID 清單 (clientIds 清單)。

如果您想讓 Endpoints API 驗證呼叫者,您必須提供一份允許要求憑證的 clientIds 清單。這份清單應包含您透過Google Cloud console 為網路或 Android 用戶端取得的所有用戶端 ID。這代表在建構 API 時,即必須提供這些用戶端。如果您指定空白清單 {},那表示沒有用戶端能存取驗證所保護的方法。

如果您使用 clientIds 屬性,且有意使用 Google API Explorer 對您的 API 進行驗證呼叫測試,則須在 clientIds 清單中提供其用戶端 ID:使用的值為com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID

關於目標對象

clientIds 清單可以「保護後端 API」,避免未經授權的用戶端存取。但是「保護用戶端」則需要進一步的防護,才能讓用戶端驗證憑證僅適用於目標後端 API。對 Android 用戶端來說,這個機制就是 audiences 屬性,您可以在其中指定後端 API 的用戶端 ID。

請注意,當您建立 Google Cloud 主控台專案時,系統會自動建立和命名提供給專案使用的預設用戶端 ID。將後端 API 上傳到 App Engine 時,會使用這個用戶端 ID,這就是 API 驗證說明中提及的網路用戶端 ID。

@ApiMethod: Method-scoped annotations

@ApiMethod 註解提供的 API 設定不同於 @Api@ApiClass 註解提供的預設 API 設定。請注意,這是選用屬性。在類別中加上 @Api 註解的所有公開、非靜態、非橋接方法,不論是否有 @ApiMethod 註解,都會在 API 中公開。

本註解中的屬性允許您設定單一 API 方法的詳細資訊。如果您在 @Api@ApiMethod 中指定相同的屬性,系統會以 @ApiMethod 內容覆寫。

必要匯入項目

如要使用這項功能,您需要匯入以下內容:

import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;

屬性

@ApiMethod 屬性 說明 範例
apiKeyRequired 選用屬性,用於限制存取提供 Api 金鑰的要求。 apiKeyRequired = AnnotationBoolean.TRUE
audiences 如要覆寫 @API 中的設定,請提供這個屬性。詳情請參閱用戶端 ID 和目標對象一節。 audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
authenticators 如果您的 API 是使用 Firebase、Auth0 或服務帳戶來進行驗證,且您並未在 API 層級設定這個屬性,則為必要屬性。如果您的 API 是使用 Google ID 憑證來進行驗證,就不需要設定這個屬性。您可以將它設為 {EspAuthenticator.class},或編寫自己的自訂驗證器,如 Interface Authenticator 頁面說明。 authenticators = {EspAuthenticator.class}
clientIds 針對可以要求憑證的用戶端,列出用戶端 ID 清單。如果 API 使用驗證,則為必要屬性。 clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
httpMethod 要使用的 HTTP 方法。如果您未設定這個屬性,則系統會根據方法名稱選擇預設值。 httpMethod = HttpMethod.GET
issuerAudiences 如要覆寫 @Api 中的設定,請提供這個屬性。 issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
metricCosts (選用步驟) 表示方法的配額有限。您將 @ApiMetricCost 註解指派給 metricCosts。您還必須指定 limitDefinitions 屬性以定義@Api 註解中的配額。@ApiMetricCost 註解具有以下屬性:
  • 名稱:您在 ApiLimitMetric 註解中指定的名稱。
  • 費用:一個整數,用於指定每次要求的費用。費用可讓方法在相同配額中以不同的速率消耗。例如,如果呼叫應用程式的配額限制為 1000 而費用為 1,則在超過限制之前,每分鐘可以提出 1000 次要求。如果呼叫應用程式在相同配額中費用為 2 時,在超過限制之前,每分鐘只能提出 500 次要求。
metricCosts = { @ApiMetricCost(name = read-requests", cost = 1) }
name 這個方法在產生的用戶端程式庫中的名稱。系統會自動在名稱前面加上 API 名稱,為方法建立不重複的名稱。name 值:
  • 「必須」以小寫字母開頭
  • 「必須」[a-z]+[A-Za-z0-9]* 規則運算式相符
如果您未指定 name,系統會使用預設的 myapi
name = "foosBall.list"
path 存取這個方法的 URI 路徑。如果您沒有設定這個屬性,系統會根據 Java 方法名稱使用預設路徑。如果您打算新增 API 管理,請勿在路徑中使用結尾的斜線。 path = "foos"
scopes 指定一個或多個 OAuth 2.0 範圍,其中一個範圍必須用來呼叫這個方法。如果您為方法設定 scopes,這個屬性會覆寫 @Api 註解中的設定。但是請注意,若您定義了多個範圍,而憑證是針對「任何」指定的範圍所新建,則會通過範圍檢查。如需多個範圍,請在每個範圍之間用一個半形空格分隔,然後只用單一 String 指定。 scopes = {"ss0", "ss1 and_ss2"}

範例 @ApiMethod 註解

這個註解是放在類別裡的方法定義前面:

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(
    name = "sayHiUser",
    httpMethod = ApiMethod.HttpMethod.GET)
public MyBean sayHiUser(@Named("name") String name, User user)
    throws OAuthRequestException, IOException {
  MyBean response = new MyBean();
  response.setData("Hi, " + name + "(" + user.getEmail() + ")");

  return response;
}

將實體當成參數的方法,應使用 HttpMethod.POST (用於插入作業) 或 HttpMethod.PUT (用於更新作業):

@ApiMethod(
    name = "mybean.insert",
    path = "mybean",
    httpMethod = ApiMethod.HttpMethod.POST
)
public void insertFoo(MyBean foo) {
}

@Named

傳送至伺服器端方法的所有非實體類型參數都須使用 @Named 註解。這個註解表示在此處注入要求中的參數名稱。未加上 @Named 註解的參數會注入整個要求物件。

必要匯入項目

如要使用這項功能,您需要匯入以下內容:

import javax.inject.Named;

這個範例示範 @Named 的用法:

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
  MyBean response = new MyBean();
  response.setData("Hi, " + name);

  return response;
}

其中 @Named 指定在要求中只注入 id 參數。

@ApiLimitMetric

本節說明為 API 定義配額所需使用的註解。如需瞭解設定配額必要的完整步驟,請參閱「設定配額」一文。

如果您將 @ApiLimitMetric 註解指派至 適用 API 範圍註解limitDefinitions 屬性,也必須針對要套用配額的每個方法,將 @ApiMetricCost 新增到 @ApiMethod 註解

必要匯入項目

如要使用這項功能,您必須匯入以下內容:

import com.google.api.server.spi.config.ApiLimitMetric;

屬性

@ApiLimitMetric 屬性

說明
name 配額名稱,通常是能夠唯一識別配額的要求類型 (例如「read-requests」或「write-requests」)
displayName 在 Google Cloud 控制台「Endpoints」 >「Services」(服務) 頁面的「Quotas」(配額) 分頁標籤中顯示的文字,用來識別配額。您的 API 消費者也會在「IAM 與管理員」及「API 與服務」的「Quotas」(配額) 頁面上看到此文字。顯示名稱的長度上限為 40 個字元。
為了便於閱讀,「Quotas」(配額) 頁面會自動為顯示名稱加上「per minute per project」(每個專案每分鐘) 字樣。
為了與 API 消費者在「Quotas」(配額) 頁面上看到的 Google 服務顯示名稱能保持一致,我們對於顯示名稱有以下建議:
  • 當您只有一個指標時,請使用「要求數」。
  • 當您有多個指標時,每個指標都應說明要求的類型,並包含「要求數」一詞 (例如「讀取要求數」或「寫入要求數」)。
  • 當這個配額的任何費用大於 1 時,請使用「配額單位」而不要使用「要求數」。
限制 整數值,針對某個配額,指定每個消費者專案每分鐘的要求數上限。

範例

limitDefinitions = {
      @ApiLimitMetric(
        name = "read-requests",
        displayName = "Read requests",
        limit = 1000),
      @ApiLimitMetric(
        name = "write-requests",
        displayName = "Write requests",
        limit = 50),
    }

@ApiNamespace

@ApiNamespace 註解可使產生的用戶端程式庫擁有您指定的命名空間,而非產生用戶端程式庫期間所建構的預設值。

按照預設,如果不使用這項註解,則系統會使用與 your-project-id.appspot.com 反向的命名空間。也就是說,套件路徑會是 com.appspot.your-project-id.yourApi

您可以透過在 @Api 註解中提供 @ApiNamespace 註解,來變更預設命名空間:

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

ownerDomain 屬性設為您自己公司的網域,並將 ownerName 設為您的公司名稱,例如 your-company.com。套件路徑會使用反向的 ownerDomaincom.your-company.yourApi

您可以選擇使用 packagePath 屬性進一步提供範圍。例如,將 packagePath 設為 cloud,用戶端程式庫中使用的套件路徑就會是 com.your-company.cloud.yourApi。您也可以在套件路徑內加入更多的值,方法是加上分隔符號 /packagePath="cloud/platform"

@Nullable

本註解表示方法參數為選用 (因此為查詢參數)。@Nullable 只能與 @Named 參數一起使用。

@ApiClass

多重類別 API 中,您可以使用 @ApiClass 為特定類別指定不同的屬性,藉此覆寫 @Api 設定中的對等屬性。如需這個註解的完整說明,請參閱「使用 @ApiClass 表示不同類別的屬性」。

@ApiReference

多重類別 API 中,您可以使用 @ApiReference 提供註解繼承的替代方法。如需這個註解的完整說明,請參閱「使用 @ApiReference 繼承」一節。

@ApiResourceProperty

@ApiResourceProperty 可讓您控管在 API 中公開資源屬性的方式。您可以在屬性 getter 或 setter 上使用此方式,以便在 API 資源中省略該屬性。如果欄位設為不公開,您可以將這個註解用於欄位本身,使其在 API 中公開。此外,這個註解也可用來更改 API 資源中的屬性名稱。

必要匯入項目

如要使用這項功能,您需要匯入以下內容:

import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.AnnotationBoolean;

屬性

@ApiResourceProperty 屬性 說明 範例
ignored 如果設定為 AnnotationBoolean.TRUE,則省略屬性。如果未指定或設定為 AnnotationBoolean.FALSE,則系統不會省略屬性。 @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
name 如果提供,會指定要在 API 中公開的屬性名稱。 @ApiResourceProperty(name = "baz")

搭配 @ApiResourceProperty 的範例類別

以下程式碼片段示範屬性 getter 加註 @ApiResourceProperty 的類別:


class Resp {
  private String foobar = "foobar";
  private String bin = "bin";

  @ApiResourceProperty
  private String visible = "nothidden";

  @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
  public String getBin() {
    return bin;
  }

  public void setBin(String bin) {
    this.bin = bin;
  }

  @ApiResourceProperty(name = "baz")
  public String getFoobar() {
    return foobar;
  }

  public void setFoobar(String foobar) {
    this.foobar = foobar;
  }
}

public Resp getResp() {
  return new Resp();
}

在上述的程式碼片段中,@ApiResourceProperty 提供給 bin 屬性的 getBin getter,同時設定了 ignored 屬性,告知 Endpoints Frameworks 在 API 資源中省略這個屬性。

@ApiResourceProperty 也會套用至未包含 getter 或 setter 的不公開欄位 visible。使用這個註解會將欄位公開成 API 資源中的屬性。

在同一個程式碼片段中,@ApiResourceProperty 也會套用至不同的 getter (getFoobar),它可以傳回 foobar 屬性的屬性值。這個註解中的 name 屬性會指示 Endpoints Frameworks 更改 API 資源中的屬性名稱。屬性值本身並不會改變。

在上述的範例程式碼片段中,Resp 物件的 JSON 表示法內容會與下列內容類似:

{"baz": "foobar", "visible": "nothidden"}

@ApiTransformer

@ApiTransformer 註解可以自訂某個類型如何透過與另一個類型之間的轉換,在 Endpoints 中公開,(指定的轉換器必須為 com.google.api.server.spi.config.Transformer)。

雖然指定轉換器時,建議對類別使用 @ApiTransformer 註解,但是您也可以在 @Api 註解的 transformer 屬性中另外指定自訂的轉換器。

必要匯入項目

如要使用這項功能,您必須匯入以下內容:

import com.google.api.server.spi.config.ApiTransformer;

搭配 @ApiTransformer 的範例類別

以下程式碼片段示範使用 @ApiTransformer 加註的類別:


@ApiTransformer(BarTransformer.class)
public class Bar {
  private final int x;
  private final int y;

  public Bar(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public int getX() {
    return x;
  }

  public int getY() {
    return y;
  }
}

系統會經由 BarTransformer 類別轉換這個類別。

Endpoints 轉換器類別範例

以下程式碼片段示範名為 BarTransformer 的範例轉換器類別。這是之前程式碼片段中,@ApiTransformer 所參考的轉換器:

public class BarTransformer implements Transformer<Bar, String> {
  public String transformTo(Bar in) {
    return in.getX() + "," + in.getY();
  }

  public Bar transformFrom(String in) {
    String[] xy = in.split(",");
    return new Bar(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
  }
}

假設有一個物件含有類型 Bar 的屬性 bar,而沒有使用上述的轉換器,則物件將與下列內容類似:

{"bar": {"x": 1, "y": 2}}

如使用轉換器,物件將與下列內容類似:

{"bar": "1,2"}