Se una singola API è particolarmente complessa, ti consigliamo di implementarla da più classi Java. Per includere classi diverse nella stessa API, devi:
- Assegna a ogni classe le stesse stringhe
name
eversion
nell'annotazione@Api
. - Aggiungi le 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à di annotazione @Api
.
Tuttavia, per più classi nella stessa API, i requisiti di @Api
vanno oltre la semplice presenza delle stesse stringhe name
e version
nell'annotazione @Api
per ogni classe. Infatti, l'API di backend non funzionerà se esistono eventuali differenze nelle configurazioni dell'API specificate nelle proprietà @Api
delle classi. Qualsiasi differenza nelle proprietà @Api
per le classi di un'API con più classi comporta una configurazione dell'API "ambigua", che non funzionerà nei framework Cloud Endpoints per App Engine.
Esistono diversi modi per creare un'API multiclasse non ambigua:
- Assicurati manualmente che tutte le classi di un'unica API abbiano le stesse proprietà di annotazione
@Api
. - Utilizza l'ereditarietà delle annotazioni tramite
l'ereditarietà Java.
In questa eredità, tutte le classi di un'unica API ereditano la stessa configurazione dell'API da una classe di base comune annotata con
@Api
. - Utilizza l'eredità delle annotazioni tramite l'annotazione
@ApiReference
su tutti i classi di un'unica API per fare in modo che facciano riferimento alla stessa configurazione dell'API da un classe comune con@Api
.
Utilizzo di @ApiClass
per le proprietà che possono variare tra le classi
Per utilizzare questa funzionalità, è necessaria la seguente importazione:
import com.google.api.server.spi.config.ApiClass;
Sebbene tutte le proprietà nell'annotazione @Api
debbano corrispondere per tutte le classi di 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 @Api
funge da valore predefinito per l'intera API. Se esiste un valore predefinito per l'intera API per la stessa proprietà, specificato in @Api
, la proprietà @ApiClass
specifica per la classe ha la precedenza sul valore predefinito per l'intera API.
Gli esempi riportati di seguito illustrano la sostituzione delle proprietà @Api
con gli equivalenti @ApiClass
specifici per 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 l'eredità Java o l'eredità @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 sottoclassificazione 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 dei 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 della proprietà resource
boards
da
BoardsBase
, sostituendo così l'impostazione della proprietà resource
(scores
) nella sua
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à ti consente di ignorare la proprietà @Api
.
Utilizzare l'ereditarietà @ApiReference
Per utilizzare questa funzionalità, è necessaria la seguente importazione:
import com.google.api.server.spi.config.ApiReference;
L'annotazione @ApiReference
fornisce un modo alternativo per specificare l'eredità delle annotazioni. Un'annotazione che utilizza @ApiReference
per specificare un'altra annotazione con @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 utilizzate sia l'eredità Java sia @ApiReference
, le annotazioni ereditano solo tramite l'annotazione @ApiReference
. Le annotazioni @Api
e @ApiClass
sulla classe ereditata tramite l'eredità 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 { … }
Sostituzione della configurazione ereditata
Indipendentemente dal fatto che la configurazione venga ereditata utilizzando l'eredità Java o @ApiReference
,
puoi sostituire la configurazione ereditata utilizzando una nuova annotazione @Api
o
@ApiClass
. Vengono sostituite solo le proprietà di configurazione specificate nella nuova annotazione. Le proprietà non specificate vengono 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 { … }
La sostituzione 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 l'eredità avviene 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 { … }
Ereditare le annotazioni @ApiMethod
L'annotazione @ApiMethod
può essere ereditata dai metodi sostituiti. 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'eredità delle annotazioni @Api
e @ApiClass
, se più metodi che si sostituiscono a vicenda hanno annotazioni @ApiMethod
, le singole proprietà possono essere sostituite. 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 l'eredità Java, non tramite
@ApiReference
.
Regole di ereditarietà e precedenza
Per riepilogare la discussione precedente, la tabella seguente mostra le regole di eredità e l'ordine di precedenza.
Annotazione/ereditarietà | Regola |
---|---|
@Api |
Deve essere identico per tutti i corsi. |
@ApiClass |
Specificato per un corso per eseguire l'override delle proprietà @Api . |
Ereditarietà Java | La classe eredita @Api e @ApiClass dalla classe di base. |
@ApiReference |
La classe eredita @Api e @ApiClass della classe a cui fa riferimento. |
Utilizzo di @ApiReference in una classe (Java) che eredita da una classe di base |
La classe eredita @Api e @ApiClass della classe a cui fa riferimento, non dalla classe di base. |
Casi d'uso comuni per l'eredità delle annotazioni
Di seguito sono riportati alcuni esempi di casi d'uso tipici per l'eredità:
Per il controllo della versione dell'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 testare versioni diverse 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;
}
}
dove someMethod
potrebbe restituire risposte predeterminate, evitare chiamate con effetti collaterali, saltare una richiesta di rete o di datastore e così via.
Aggiunta dei corsi a web.xml
Dopo aver annotato i tuoi corsi, devi aggiungerli al 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 classe all'interno dello stesso campo
<param-value>
separato da una virgola, ad esempio:<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>