Si una API es compleja, es posible que desees implementarla desde varias clases de Java. Para que diferentes clases formen parte de la misma API, realiza lo siguiente:
- Otorga a cada clase las mismas strings de
name
yversion
en su anotación@Api
. - Agrega las API de clase como una lista separada por comas en
web.xml
.
Por ejemplo, las dos clases siguientes son parte de la API de tictactoe
:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
La configuración de la API se especifica a través de las propiedades de la anotación @Api
.
Sin embargo, para varias clases en la misma API, los requisitos de @Api
no se tratan solo de tener las mismas strings de name
y version
en la anotación @Api
de cada clase. No puede haber ninguna diferencia en la configuración de la API especificada en las propiedades de @Api
de la clase, de lo contrario, tu API de backend no funcionará. Las diferencias en las propiedades de @Api
para las clases de una API multiclase generan una configuración de API “ambigua”, que no funcionará en Cloud Endpoints Frameworks para App Engine.
Existen varias maneras de crear una API multiclase que no sea ambigua:
- De forma manual, asegúrate de que todas las clases en una sola API tengan las mismas propiedades que la anotación
@Api
. - Usa la herencia de anotación mediante la herencia de Java.
En esta herencia, todas las clases en una sola API heredan la misma configuración de API a partir de una clase en común básica anotada con
@Api
. - Usa la herencia de anotación a través de la anotación
@ApiReference
en todas las clases de una sola API para hacer referencia a la misma configuración de API a partir de una clase en común anotada con@Api
.
Usa @ApiClass
para propiedades que pueden diferir entre clases
Para usar esta característica necesitas la importación siguiente:
import com.google.api.server.spi.config.ApiClass;
Si bien todas las propiedades en la anotación @Api
deben coincidir en todas las clases de una API, también puedes usar la anotación @ApiClass
para proporcionar propiedades que no deben ser idénticas entre las clases. Por ejemplo:
// 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 { … }
aquí TicTacToeA
limita el acceso mediante una lista blanca de ID de cliente que contienen el ID de cliente permitido, y TicTacToeB
no limita el acceso.
Todas las propiedades proporcionadas por la anotación @ApiClass
tienen una propiedad equivalente en la anotación @Api
. Ten en cuenta que la propiedad equivalente de @Api
actúa como la propiedad predeterminada en toda la API. Si hay una configuración predeterminada en toda la API para esa misma propiedad, especificada en @Api
, la propiedad de @ApiClass
específica de la clase anula la configuración predeterminada en toda la API.
En los siguientes ejemplos, se ilustra la anulación de las propiedades de @Api
por parte de las equivalentes de @ApiClass
específicas de la clase:
// 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 { … }
Herencia de anotación
Las propiedades de anotación de @Api
y @ApiClass
pueden heredarse de otras clases y las propiedades individuales pueden anularse mediante la herencia de Java o la herencia de @ApiReference
.
Usa la herencia de Java
Una clase que extiende otra clase con anotaciones @Api
o @ApiClass
se comporta como si estuviera anotada con las mismas propiedades. Por ejemplo:
@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 { … }
Las anotaciones solo se heredan mediante la subclasificación de Java, no mediante la implementación de la interfaz. Por ejemplo:
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
Por lo tanto, no se admite ningún tipo de herencia múltiple de anotaciones de marcos de trabajo.
La herencia también funciona para @ApiClass
, como se muestra a continuación:
@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 { … }
aquí TicTacToeBoards
hereda el valor boards
de la propiedad resource
desde BoardsBase
, lo que anula la configuración de la propiedad resource
(scores
) en su anotación @Api
. Recuerda que si alguna clase especificó la propiedad de recurso en la anotación @Api
, todas las clases deben especificar esa misma configuración en la anotación @Api
. Esta técnica de herencia te permite anular esa propiedad de @Api
.
Usa la herencia de @ApiReference
Para usar esta característica necesitas la importación siguiente:
import com.google.api.server.spi.config.ApiReference;
La anotación @ApiReference
proporciona una forma alternativa de especificar la herencia de la anotación. Una clase que usa @ApiReference
para especificar otra clase con anotaciones @Api
o @ApiClass
se comporta como si estuviera anotada con las mismas propiedades. Por ejemplo:
@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 se usan la herencia de Java y @ApiReference
, las anotaciones se heredan solo a través de la anotación @ApiReference
. Las anotaciones @Api
y @ApiClass
de la clase heredadas a través de la herencia de Java se ignoran. Por ejemplo:
@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 { … }
Anula la configuración heredada
Ya sea que heredes la configuración mediante la herencia de Java o @ApiReference
, puedes anular la configuración heredada con una nueva anotación @Api
o @ApiClass
. Solo se anulan las propiedades de configuración especificadas en la anotación nueva. Las propiedades que no se especifican sí se heredan.
Por ejemplo:
@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 anulación de la herencia también funciona para @ApiClass
, como se muestra a continuación:
@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 { … }
La anulación también funciona cuando se hereda a través de @ApiReference
, como se ilustra a continuación:
@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 { … }
Hereda anotaciones @ApiMethod
La anotación @ApiMethod
se puede heredar de métodos anulados. Por ejemplo:
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) { … }
}
Al igual que con la herencia de las anotaciones @Api
y @ApiClass
, si varios métodos que se anulan entre sí tienen anotaciones @ApiMethod
, las propiedades individuales se pueden anular. Por ejemplo:
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) { … }
}
No hay ninguna anotación @ApiReference
o equivalente para los métodos, por lo que @ApiMethod
siempre se hereda a través de la herencia de Java, no a través de @ApiReference
.
Reglas de herencia y precedencia
Para resumir la explicación anterior, en la tabla que aparece a continuación, se muestran las reglas de herencia y el orden de precedencia.
Anotación/herencia | Regla |
---|---|
@Api |
Debe ser idéntica para todas las clases. |
@ApiClass |
Se especifica para que una clase anule las propiedades de @Api . |
Herencia de Java | La clase hereda @Api y @ApiClass de la clase básica. |
@ApiReference |
La clase hereda @Api y @ApiClass de la clase a la que se hace referencia. |
Usar @ApiReference en una clase (Java) que hereda de una clase básica |
La clase hereda @Api y @ApiClass de la clase a la que se hace referencia, no de la clase básica. |
Casos prácticos comunes de herencia de anotación
A continuación, se muestran ejemplos de los casos prácticos típicos de la herencia:
Para el control de versiones de la API:
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
Para API multiclase:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
Para probar diferentes versiones de la misma 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;
}
}
aquí someMethod
podría mostrar respuestas predeterminadas, evitar llamadas con efectos secundarios, omitir una solicitud de red o almacén de datos y demás.
Agrega las clases a web.xml
Después de anotar tus clases, debes agregarlas a tu archivo web.xml
. El ejemplo siguiente muestra una sola clase:
Para agregar clases múltiples, sigue estos pasos:
Reemplaza
<param-value>com.example.skeleton.MyApi</param-value>
por tu propio nombre de clase de API.Agrega todas las clases dentro del mismo campo
<param-value>
separadas por una coma, como se muestra a continuación:<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>