Si l'une de vos API est particulièrement complexe, vous pouvez la mettre en œuvre à partir de plusieurs classes Java. Pour que différentes classes fassent partie de la même API, vous devez :
- attribuer à chaque classe les mêmes chaînes
name
etversion
dans son annotation@Api
; - ajouter des API de classe sous forme de liste d'éléments séparés par une virgule dans
web.xml
.
Par exemple, les deux classes suivantes font toutes les deux partie de l'API tictactoe
:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
La configuration de l'API est spécifiée via les propriétés de l'annotation @Api
.
Toutefois, dans le cas des API multiclasses, les exigences de l'annotation @Api
vont au-delà du simple partage de la même valeur pour name
et version
dans l'annotation @Api
de chaque classe. En fait, votre API backend ne fonctionnera pas s'il existe la moindre différence dans les configurations d'API spécifiées dans les propriétés @Api
des classes. Toute différence au sein des propriétés @Api
dans une API multiclasse entraîne une configuration "ambiguë" de l'API, qui ne fonctionnera pas dans Cloud Endpoints Frameworks pour App Engine.
Il existe plusieurs façons de créer une API multiclasse et non ambiguë :
- Vérifiez manuellement que toutes les classes d'une API ont exactement les mêmes propriétés d'annotation
@Api
. - Utilisez l'héritage d'annotation via la fonctionnalité d'héritage Java.
Ainsi, toutes les classes d'une API héritent de la configuration d'API d'une classe de base commune définie par l'annotation
@Api
. - Utilisez l'héritage d'annotation
@ApiReference
sur toutes les classes d'une même API afin qu'elles référencent la même configuration d'API d'une classe commune définie par l'annotation@Api
.
Utiliser @ApiClass
pour les propriétés pouvant différer entre des classes
Pour utiliser cette fonctionnalité, vous avez besoin de l'importation suivante :
import com.google.api.server.spi.config.ApiClass;
Bien que toutes les propriétés de l'annotation @Api
doivent correspondre pour toutes les classes d'une API, vous pouvez également utiliser l'annotation @ApiClass
pour fournir des propriétés qui ne doivent pas nécessairement être identiques entre les classes. Par exemple :
// 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 { … }
où TicTacToeA
limite l'accès en utilisant une liste blanche d'ID clients contenant l'ID client autorisé, et où TicTacToeB
ne limite pas l'accès.
Toutes les propriétés fournies par l'annotation @ApiClass
ont une propriété équivalente dans l'annotation @Api
. Notez que la propriété @Api
équivalente sert de valeur par défaut au niveau de l'API. Si une valeur par défaut au niveau de l'API est spécifiée pour cette propriété dans @Api
, la propriété @ApiClass
, propre à une classe, la remplace.
Les exemples suivants illustrent le remplacement des propriétés @Api
par les équivalents @ApiClass
propres à une classe :
// 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 { … }
Héritage d'annotation
Les propriétés d'annotation @Api
et @ApiClass
peuvent être héritées d'autres classes, et des propriétés individuelles peuvent être remplacées via l'héritage Java ou l'héritage @ApiReference
.
Utiliser l'héritage Java
Une classe qui étend une autre classe avec des annotations @Api
ou @ApiClass
se comportera comme si elle était annotée avec les mêmes propriétés. Exemple :
@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 { … }
Les annotations ne sont héritées que par la définition de sous-classes Java et non par la mise en œuvre d'une interface. Par exemple :
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
Par conséquent, il n'existe aucune compatibilité avec les héritages multiples d'annotations de frameworks.
L'héritage fonctionne également pour @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 { … }
où TicTacToeBoards
hérite de BoardsBase
la valeur boards
pour la propriété resource
, remplaçant ainsi le paramètre de la propriété resource
(scores
) dans son annotation @Api
. Gardez à l'esprit que si une classe a spécifié la propriété de ressource dans l'annotation @Api
, toutes les classes doivent spécifier le même paramètre dans leur annotation @Api
. Cette technique d'héritage vous permet de remplacer cette propriété @Api
.
Utiliser l'héritage @ApiReference
Pour utiliser cette fonctionnalité, vous avez besoin de l'importation suivante :
import com.google.api.server.spi.config.ApiReference;
L'annotation @ApiReference
fournit un autre moyen de spécifier l'héritage d'annotation. Une classe qui utilise @ApiReference
pour spécifier une autre classe avec des annotations @Api
ou @ApiClass
se comportera comme si elle était annotée avec les mêmes propriétés. Exemple :
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA behaves as if it has the same @Api annotation as TicTacToeBase
@ApiReference(TicTacToeBase.class)
class TicTacToeA { … }
Si l'héritage Java et @ApiReference
sont utilisés conjointement, seul l'héritage @ApiReference
fonctionnera. Les annotations @Api
et @ApiClass
sur la classe héritée via l'héritage Java sont ignorées. Exemple :
@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 { … }
Remplacer une configuration héritée
Qu'une configuration soit héritée via l'héritage Java ou via @ApiReference
, vous pouvez la remplacer à l'aide d'une nouvelle annotation @Api
ou @ApiClass
. Seules les propriétés de configuration spécifiées dans la nouvelle annotation sont remplacées. Les propriétés non spécifiées sont toujours héritées.
Exemple :
@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 { … }
Le remplacement de l'héritage fonctionne également pour @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 { … }
Le remplacement fonctionne aussi lors de l'héritage via @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 { … }
Hériter des annotations @ApiMethod
L'annotation @ApiMethod
peut être héritée via des méthodes de remplacement. Exemple :
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) { … }
}
Comme pour l'héritage d'annotations @Api
et @ApiClass
, si plusieurs méthodes de remplacement ont des annotations @ApiMethod
, des propriétés individuelles peuvent être remplacées. Exemple :
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) { … }
}
Il n'existe pas d'annotation @ApiReference
ni d'équivalent pour les méthodes. Par conséquent, @ApiMethod
est toujours héritée via l'héritage Java et non via @ApiReference
.
Règles d'héritage et de priorité
Pour synthétiser les points abordés jusqu'ici, le tableau ci-dessous présente les règles d'héritage et l'ordre de priorité respecté.
Annotation/Héritage | Règle |
---|---|
@Api |
Doit être identique pour toutes les classes. |
@ApiClass |
Spécifiée pour qu'une classe remplace les propriétés @Api . |
Héritage Java | La classe hérite des propriétés @Api et @ApiClass de la classe de base. |
@ApiReference |
La classe hérite des propriétés @Api et @ApiClass de la classe référencée. |
Utilisation de @ApiReference sur une classe (Java) héritant d'une classe de base |
La classe hérite des propriétés @Api et @ApiClass de la classe référencée, pas de la classe de base. |
Cas d'utilisation courants pour l'héritage d'annotation
Vous trouverez ci-dessous des cas d'utilisation typiques pour l'héritage :
Pour la gestion des versions d'API :
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
Pour les API multiclasses :
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
Pour tester différentes versions de la même 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;
}
}
où someMethod
peut renvoyer des réponses prédéterminées, éviter les appels ayant des effets secondaires, ignorer une requête issue d'un réseau ou d'un datastore, etc.
Ajouter les classes à web.xml
Après avoir annoté vos classes, vous devez les ajouter à votre fichier web.xml
. L'exemple suivant montre une classe unique :
Pour ajouter plusieurs classes :
Remplacez
<param-value>com.example.skeleton.MyApi</param-value>
par le nom de votre classe d'API.Ajoutez chaque classe dans le même champ
<param-value>
en les séparant par une virgule, par exemple :<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>