Se una singola API è particolarmente complessa, potresti volerla implementare da più classi Java. Per rendere diverse classi parte della stessa API, devi:
- Assegna a ogni classe le stesse stringhe
name
eversion
nell'annotazione@Api
. - Aggiungi API di classe come elenco separato da virgole in
web.xml
.
Ad esempio, le due classi seguenti fanno entrambe parte dell'API tictactoe
:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
La configurazione dell'API viene specificata tramite le proprietà dell'annotazione @Api
.
Tuttavia, per più classi nella stessa API, i requisiti @Api
si estendono
oltre ad avere semplicemente le stesse stringhe name
e version
nell'annotazione @Api
per ogni classe. Infatti, l'API di backend non funziona in caso di eventuali differenze nelle configurazioni API specificate nelle proprietà @Api
delle classi. Qualsiasi differenza nelle proprietà @Api
per le classi in un'API multiclass comporta una configurazione dell'API "ambigua", che non funziona nei framework Cloud Endpoints per App Engine.
Esistono diversi modi per creare un'API multiclasse non ambigua:
- Assicurati manualmente che tutte le classi in una singola API abbiano le stesse proprietà di annotazione
@Api
. - Utilizza l'ereditarietà delle annotazioni tramite
l'ereditarietà Java.
In questa ereditarietà, tutte le classi in una singola API ereditano la stessa configurazione API da una classe base comune con annotazioni
@Api
. - Utilizza l'ereditarietà delle annotazioni tramite l'annotazione
@ApiReference
su tutte le classi in una singola API in modo che facciano riferimento alla stessa configurazione API di una classe comune annotata su@Api
.
Utilizzo di @ApiClass
per le proprietà che possono variare da una classe all'altra
Per utilizzare questa funzionalità, devi eseguire la seguente importazione:
import com.google.api.server.spi.config.ApiClass;
Mentre tutte le proprietà nell'annotazione @Api
devono corrispondere a tutte le classi in un'API, puoi utilizzare anche l'annotazione @ApiClass
per fornire proprietà
che non devono essere esattamente uguali tra le classi. Ad esempio:
// 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 { … }
dove TicTacToeA
limita l'accesso utilizzando una lista consentita di ID client contenente
l'ID client consentito e TicTacToeB
non limita l'accesso.
Tutte le proprietà fornite dall'annotazione @ApiClass
hanno una proprietà
equivalente nell'annotazione @Api
. Tieni presente che la proprietà equivalente di @Api
agisce
da impostazione predefinita a livello di API. Se esiste un'impostazione predefinita a livello di API per la stessa proprietà specificata in @Api
, la proprietà @ApiClass
specifica della classe sostituisce l'impostazione predefinita a livello di API.
I seguenti esempi mostrano l'override delle proprietà @Api
da parte degli equivalenti di @ApiClass
specifici della 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 { … }
Eredità delle annotazioni
Le proprietà di annotazione @Api
e @ApiClass
possono essere ereditate da
altre classi e le singole proprietà possono essere sostituite tramite
ereditarietà Java
o
ereditarietà @ApiReference
Utilizzo dell'ereditarietà Java
Una classe che estende un'altra classe con annotazioni @Api
o @ApiClass
si comporta come se fosse annotata con le stesse proprietà. Ad esempio:
@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 { … }
Le annotazioni vengono ereditate solo tramite la sottoclasse Java, non tramite l'implementazione dell'interfaccia. Ad esempio:
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
Di conseguenza, non è supportato alcun tipo di ereditarietà multipla delle annotazioni framework.
L'ereditarietà funziona anche per @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 { … }
dove TicTacToeBoards
eredita il valore boards
della proprietà resource
da
BoardsBase
, sostituendo così l'impostazione della proprietà resource
(scores
) nella relativa
annotazione @Api
. Ricorda che se una classe ha specificato la proprietà della risorsa nell'annotazione @Api
, tutte le classi devono specificare la stessa impostazione nell'annotazione @Api
; questa tecnica di ereditarietà consente di ignorare la proprietà @Api
.
Utilizzo dell'ereditarietà @ApiReference
Per utilizzare questa funzionalità, devi eseguire la seguente importazione:
import com.google.api.server.spi.config.ApiReference;
L'annotazione @ApiReference
fornisce un modo alternativo per specificare l'ereditarietà dell'annotazione. Una classe che utilizza @ApiReference
per specificare un'altra classe con annotazioni
@Api
o @ApiClass
si comporta come se fosse annotata con le stesse
proprietà. Ad esempio:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA behaves as if it has the same @Api annotation as TicTacToeBase
@ApiReference(TicTacToeBase.class)
class TicTacToeA { … }
Se vengono utilizzati sia l'ereditarietà Java sia @ApiReference
, le annotazioni ereditano solo tramite l'annotazione @ApiReference
. Le annotazioni @Api
e @ApiClass
sulla classe ereditata tramite l'ereditarietà Java vengono ignorate. Ad
esempio:
@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 { … }
Override della configurazione ereditata
Che tu erediti la configurazione utilizzando l'ereditarietà Java o @ApiReference
, puoi sostituire la configurazione ereditata utilizzando una nuova annotazione @Api
o @ApiClass
. Viene eseguito l'override solo delle proprietà di configurazione specificate nella nuova annotazione. Le proprietà non specificate verranno comunque ereditate.
Ad esempio:
@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 { … }
L'override dell'ereditarietà funziona anche per @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 { … }
L'override funziona anche quando si eredita tramite @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 { … }
Ereditarietà di @ApiMethod
annotazioni in corso...
L'annotazione @ApiMethod
può essere ereditata dai metodi sottoposti a override. Ad
esempio:
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) { … }
}
Analogamente all'ereditarietà delle annotazioni @Api
e @ApiClass
, se più metodi che eseguono l'override l'uno dell'altro hanno annotazioni @ApiMethod
, è possibile eseguire l'override delle singole proprietà. Ad esempio:
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) { … }
}
Non esiste un'annotazione @ApiReference
o un equivalente per i metodi, quindi
@ApiMethod
viene sempre ereditato tramite ereditarietà Java, non tramite
@ApiReference
.
Regole di ereditarietà e di precedenza
Per sintetizzare la discussione precedente, la tabella seguente mostra le regole di ereditarietà e l'ordine di precedenza.
Annotazione/ereditarietà | Regola |
---|---|
@Api |
Deve essere identico per tutti i corsi. |
@ApiClass |
Specificato per una classe per sostituire @Api proprietà. |
Eredità Java | La classe eredita @Api e @ApiClass della classe base. |
@ApiReference |
La classe eredita @Api e @ApiClass della classe di riferimento. |
Utilizzo di @ApiReference su una classe (Java) che eredita da una classe base |
La classe eredita @Api e @ApiClass della classe di riferimento, non dalla classe base. |
Casi d'uso comuni per l'ereditarietà delle annotazioni
Di seguito sono riportati alcuni esempi dei tipici casi d'uso dell'ereditarietà:
Per il controllo delle versioni delle API:
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
Per le API multiclasse:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
Per eseguire test su diverse versioni della stessa 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;
}
}
in cui someMethod
potrebbe restituire risposte predeterminate, evitare chiamate con effetti collaterali, saltare una richiesta di rete o datastore e così via.
Aggiunta dei corsi a web.xml
in corso...
Dopo aver annotato i corsi, devi aggiungerli al tuo file web.xml
. L'esempio seguente mostra una singola classe:
Per aggiungere più corsi:
Sostituisci
<param-value>com.example.skeleton.MyApi</param-value>
con il nome della tua classe API.Aggiungi ogni corso all'interno dello stesso campo
<param-value>
separati da una virgola, ad esempio:<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>