Wenn eine einzelne API besonders komplex ist, wollen Sie sie möglicherweise von mehreren Java-Klassen implementieren. Um derselben API verschiedene Klassen zuzuordnen, müssen Sie
- Legen Sie für jede Klasse die gleichen Strings für nameundversionin der Annotation@Apifest.
- Fügen Sie Klassen-APIs als durch Kommas getrennte Liste in web.xmlein.
Die folgenden beiden Klassen sind z. B. Teil der tictactoe API:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
Die API-Konfiguration wird durch die Attribute in der Annotation @Api festgelegt.
Die Anforderungen @Api für mehrere Klassen in der gleichen API sind allerdings nicht schon durch die gleichen Strings für name und version in der Annotation @Api erfüllt. Die Back-End API funktioniert nicht, wenn in den API-Konfigurationen, die in den Attributen @Api der Klasse festgelegt sind, irgendwelche Abweichungen vorliegen. Jeder Unterschied in den @Api-Attributen von Klassen in einer API mit mehreren Klassen führt zu einer nicht eindeutigen API-Konfiguration, die in Cloud Endpoints Frameworks für App Engine nicht funktioniert.
Eine eindeutige mehrklassige API kann auf mehrere Arten erstellt werden:
- Stellen Sie manuell sicher, dass alle Klassen einer einzelnen API die exakt gleichen Attribute in der Annotation @Apihaben.
- Verwenden Sie die Übernahme der Annotation durch Java-Übernahme.
Bei dieser Übernahme übernehmen alle Klassen in einer einzelnen API die gleiche API-Konfiguration von einer gemeinsamen @Api-annotierten Standardklasse.
- Verwenden Sie die Übernahme der Annotation mithilfe der @ApiReference-Annotation für alle Klassen in einer einzelnen API, sodass sie dieselbe API-Konfiguration von einer gemeinsamen@Api-annotierten Klasse beziehen.
@ApiClass für abweichende Attribute in Klassen verwenden
Für diese Funktion ist der folgende Import erforderlich:
import com.google.api.server.spi.config.ApiClass;
Obwohl alle Attribute in der Annotation @Apifür alle Klassen in der API übereinstimmen müssen, können Sie zusätzlich mit der Annotation @ApiClass Attribute bereitstellen, die nicht zwingend übereinstimmen müssen. Beispiel:
// API methods implemented in this class allow only "clientIdA".
@Api(name = "tictactoe", version = "v1")
@ApiClass(clientIds = { "clientIdA" })
class TicTacToeA { … }
// API methods implemented in this class provide unauthenticated access.
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
Dabei beschränkt TicTacToeA den Zugriff mithilfe einer weißen Liste mit Client-IDs mit der zulässigen Client-ID. TicTacToeB beschränkt den Zugriff nicht.
Alle von der Annotation @ApiClass zur Verfügung gestellten Attribute haben ein äquivalentes Attribut in der Annotation @Api. Beachten Sie, dass das @Api-äquivalente Attribut als API-weiter Standard gilt. Wenn es einen API-weiten Standard für dasselbe in @Api angegebene Attribut gibt, überschreibt das klassenspezifische Attribut @ApiClass den API-weiten Standard.
Das folgende Beispiel zeigt, wie die klassenspezifischen @ApiClass-Äquivalente die @Api-Attribute überschreiben:
// For this class "boards" overrides "games".
@Api(name = "tictactoe", version = "v1", resource = "games")
@ApiClass(resource = "boards")
class TicTacToeBoards { … }
// For this class "scores" overrides "games".
@Api(name = "tictactoe", version = "v1", resource = "games")
@ApiClass(resource = "scores")
class TicTacToeScores { … }
// For this class, the API-wide default "games" is used as the resource.
@Api(name = "tictactoe", version = "v1", resource = "games")
class TicTacToeGames { … }
Annotationsübernahme
Die Annotationsattribute @Api und @ApiClass können von anderen Klassen übernommen und einzelne Attribute durch Java-Übernahme oder @ApiReference-Übernahme überschrieben werden.
Java-Übernahme verwenden
Eine Klasse, die eine andere Klasse mit @Api- oder @ApiClass-Annotationen erweitert, verhält sich so, als ob sie mit denselben Attributen annotiert wäre. Beispiel:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA and TicTacToeB both behave as if they have the same @Api annotation as
// TicTacToeBase
class TicTacToeA extends TicTacToeBase { … }
class TicTacToeB extends TicTacToeBase { … }
Annotationen werden nur durch Java-Subklassen übernommen, nicht durch Schnittstellenimplementierung. Beispiel:
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
Daraus folgt, dass es keine Unterstützung für jegliche Form der mehrfachen Übernahme von Frameworks-Annotationen gibt.
Die Übernahme funktioniert auch für @ApiClass:
@ApiClass(resource = "boards")
class BoardsBase { … }
// TicTacToeBoards behaves as if annotated with the @ApiClass from BoardsBase.
// Thus, the "resource" property will be "boards".
@Api(name = "tictactoe", version = "v1", resource = "scores")
class TicTacToeBoards extends BoardsBase { … }
Dabei übernimmt TicTacToeBoards den resource-Attributwert boards von BoardsBase und überschreibt damit die resource-Attributeinstellung (scores) in der Annotation @Api. Denken Sie daran, dass alle Klassen die gleiche Einstellung in der Annotation @Api angeben müssen, falls eine Klasse das Ressourcenattribut in der Annotation @Api angegeben hat. Mit dieser Methode der Übernahme können Sie das Attribut @Api überschreiben.
@ApiReference-Übernahme verwenden
Für diese Funktion ist der folgende Import erforderlich:
import com.google.api.server.spi.config.ApiReference;
Die Annotation @ApiReference bietet eine Alternative, um die Übernahme der Annotation anzugeben. Eine Klasse, die @ApiReference verwendet, um eine andere Klasse mit @Api- oder @ApiClass-Annotationen anzugeben, verhält sich so, als ob sie mit denselben Attributen annotiert wäre. Beispiel:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA behaves as if it has the same @Api annotation as TicTacToeBase
@ApiReference(TicTacToeBase.class)
class TicTacToeA { … }
Wenn sowohl die Java-Übernahme als auch @ApiReference verwendet werden, erfolgt die Übernahme nur durch die Annotation @ApiReference. @Api- und @ApiClass-Annotationen für die durch Java-Übernahme übernommene Klasse werden ignoriert. Beispiel:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBaseA { … }
@Api(name = "tictactoe", version = "v2")
class TicTacToeBaseB { … }
// TicTacToe will behave as if annotated the same as TicTacToeBaseA, not TicTacToeBaseB.
// The value of the "version" property will be "v1".
@ApiReference(TicTacToeBaseA.class)
class TicTacToe extends TicTacToeBaseB { … }
Übernommene Konfiguration überschreiben
Unabhängig davon, ob Sie die Konfiguration mithilfe von Java-Übernahme oder @ApiReference übernehmen, können Sie die übernommene Konfiguration mit einer neuen @Api- oder @ApiClass-Annotation überschreiben. Nur in der neuen Annotation angegebene Konfigurationsattribute werden überschrieben. Attribute, die nicht angegeben sind, werden trotzdem übernommen.
Beispiel:
@Api(name = "tictactoe", version = "v2")
class TicTacToe { … }
// Checkers will behave as if annotated with name = "checkers" and version = "v2"
@Api(name = "checkers")
class Checkers extends TicTacToe { … }
Das Überschreiben von Übernahmen funktioniert auch für @ApiClass:
@Api(name = "tictactoe", version = "v1")
@ApiClass(resource = "boards", clientIds = { "c1" })
class Boards { … }
// Scores will behave as if annotated with resource = "scores" and clientIds = { "c1" }
@ApiClass(resource = "scores")
class Scores { … }
Das Überschreiben funktioniert auch für Übernahmen mithilfe von @ApiReference:
@Api(name = "tictactoe", version = "v2")
class TicTacToe { … }
// Checkers will behave as if annotated with name = "checkers" and version = "v2"
@ApiReference(TicTacToe.class)
@Api(name = "checkers")
class Checkers { … }
@ApiMethod-Annotationen übernehmen
Die Annotation @ApiMethod kann von überschriebenen Methoden übernommen werden. Beispiel:
class TicTacToeBase {
  @ApiMethod(httpMethod = "POST")
  public Game setGame(Game game) { … }
}
@Api(name = "tictactoe", version = "v1")
class TicTacToe extends TicTacToeBase {
  // setGame behaves as if annotated with the @ApiMethod from TicTacToeBase.setGame.
  // Thus the "httpMethod" property will be "POST".
  @Override
  public Game setGame(Game game) { … }
}
Ähnlich wie bei der Übernahme von @Api- und @ApiClass-Annotationen können einzelne Attribute überschrieben werden, wenn mehrere sich überschreibende Methoden @ApiMethod-Annotationen haben. Beispiel:
class TicTacToeBase {
  @ApiMethod(httpMethod = "POST", clientIds = { "c1" })
  public Game setGame(Game game) { … }
}
@Api(name = "tictactoe", version = "v1")
class TicTacToe extends TicTacToeBase {
  // setGame behaves as if annotated with httpMethod = "GET" and clientIds = { "c1"}.
  @ApiMethod(httpMethod = "GET")
  @Override
  public Game setGame(Game game) { … }
}
Es gibt keine @ApiReference-Annotation oder -Äquivalent für Methoden, also wird @ApiMethod immer durch Java-Übernahme übernommen, nicht durch @ApiReference.
Übernahme- und Vorrangregeln
Zur Zusammenfassung der obigen Diskussion zeigt die folgende Tabelle die Übernahmeregeln und die Reihenfolge des Vorrangs.
| Annotation/Übernahme | Regel | 
|---|---|
| @Api | Muss für alle Klassen gleich sein. | 
| @ApiClass | Angegeben für eine Klasse, um @Api-Attribute zu überschreiben. | 
| Java-Übernahme | Die Klasse übernimmt @Apiund@ApiClassder Standardklasse. | 
| @ApiReference | Die Klasse übernimmt @Apiund@ApiClassder Referenzklasse. | 
| @ApiReferenceauf eine Klasse (Java) anwenden, die von einer Standardklasse übernimmt. | Klasse übernimmt @Apiund@ApiClassder Referenzklasse, nicht der Standardklasse. | 
Häufige Anwendungsfälle für die Annotationsübernahme
Die folgenden Beispiele zeigen typische Anwendungsfälle für die Übernahme:
Für API-Versionierung:
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
Für APIs mit mehreren Klassen:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
Zum Testen verschiedener Versionen der gleichen API:
@Api(name = "tictactoe", version = "v1")
class TicTacToe {
  protected Foo someMethod() {
    // Do something real;
  }
  public Foo getFoo() { … }
}
@Api(version="v1test")
class TicTacToeTest extends TicTacToe {
  protected Foo someMethod() {
    // Stub out real action;
  }
}
Dabei gibt someMethod möglicherweise die vorgegebenen Antworten zurück, verhinderte Aufrufe mit Nebenwirkungen, überspringt eine Netzwerk- oder Datastore-Anfrage usw.
Klassen zu web.xml hinzufügen
Nachdem die Klassen annotiert wurden, müssen sie der Datei web.xml hinzugefügt werden. Das folgende Beispiel enthält eine einzelne Klasse:
So fügen Sie mehrere Klassen hinzu:
- Ersetzen Sie - <param-value>com.example.skeleton.MyApi</param-value>durch den API-Klassennamen.
- Fügen Sie jede Klasse jeweils durch ein Komma getrennt innerhalb dieses - <param-value>-Felds ein. Beispiel:- <param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>