Si una API es especialmente compleja, puede que quieras implementarla desde varias clases de Java. Para que diferentes clases formen parte de la misma API, debes hacer lo siguiente:
- Asigna a cada clase las mismas cadenas
name
yversion
en su anotación@Api
. - Añade las APIs de clase como una lista separada por comas en
web.xml
.
Por ejemplo, las dos clases siguientes forman parte de la API tictactoe
:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
La configuración de la API se especifica mediante las propiedades de anotación @Api
.
Sin embargo, en el caso de varias clases en la misma API, los requisitos de @Api
van más allá de tener las mismas cadenas name
y version
en la anotación @Api
de cada clase. De hecho, tu API de backend no funcionará si hay alguna diferencia en las configuraciones de la API especificadas en las propiedades @Api
de las clases. Si hay alguna diferencia en las propiedades @Api
de las clases de un resultado de API de varias clases, la configuración de la API será ambigua y no funcionará en Cloud Endpoints Frameworks para App Engine.
Hay varias formas de crear una API multiclass inequívoca:
- Asegúrate manualmente de que todas las clases de una misma API tengan exactamente las mismas propiedades de anotación
@Api
. - Usa la herencia de anotaciones mediante la herencia de Java.
En esta herencia, todas las clases de una sola API heredan la misma configuración de API de una clase base común anotada con
@Api
. - Usa la herencia de anotaciones a través de la anotación
@ApiReference
en todas las clases de una misma API para que hagan referencia a la misma configuración de la API desde una clase común con la anotación@Api
.
Usar @ApiClass
para propiedades que pueden variar entre clases
Para usar esta función, necesitas la siguiente importación:
import com.google.api.server.spi.config.ApiClass;
Aunque todas las propiedades de 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 tengan que ser exactamente iguales entre 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 { … }
donde TicTacToeA
limita el acceso mediante una lista blanca de IDs de cliente que contiene 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 @Api
actúa como valor predeterminado en toda la API. Si hay un valor predeterminado para toda la API para esa misma propiedad, especificado en @Api
, la propiedad @ApiClass
específica de la clase anula el valor predeterminado de toda la API.
En los siguientes ejemplos se muestra cómo se anulan las propiedades @Api
mediante los equivalentes @ApiClass
específicos 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 { … }
Heredados de la anotación
Las propiedades de anotación @Api
y @ApiClass
se pueden heredar de otras clases, y las propiedades individuales se pueden anular mediante la herencia de Java o la herencia de @ApiReference
.
Usar la herencia de Java
Una clase que amplía otra clase con anotaciones @Api
o @ApiClass
se comporta como si tuviera 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 a través de las subclases de Java, no a través de la implementación de interfaces. 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 frameworks.
La herencia también funciona con @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 { … }
donde TicTacToeBoards
hereda el valor de la propiedad resource
(boards
) de BoardsBase
, lo que anula la configuración de la propiedad resource
(scores
) en su anotación @Api
. Recuerda que, si alguna clase ha especificado la propiedad de recurso en la anotación @Api
, todas las clases deben especificar el mismo ajuste en la anotación @Api
. Esta técnica de herencia te permite anular la propiedad @Api
.
Usar la herencia de @ApiReference
Para usar esta función, necesitas la siguiente importación:
import com.google.api.server.spi.config.ApiReference;
La anotación @ApiReference
proporciona una forma alternativa de especificar la herencia de anotaciones. Una clase que usa @ApiReference
para especificar otra clase con anotaciones @Api
o @ApiClass
se comporta como si tuviera 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 tanto la herencia de Java como @ApiReference
, las anotaciones se heredarán solo a través de la anotación @ApiReference
. Se ignoran las anotaciones @Api
y @ApiClass
de la clase heredada a través de la herencia de Java. 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 { … }
Anular la configuración heredada
Tanto si heredas la configuración mediante la herencia de Java como si lo haces con @ApiReference
,
puedes anular la configuración heredada usando una nueva anotación @Api
o @ApiClass
. Solo se anulan las propiedades de configuración especificadas en la nueva anotación. Las propiedades que no se especifican se siguen heredando.
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 con @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 { … }
La anulación también funciona cuando se hereda a través de @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 { … }
Heredar anotaciones de @ApiMethod
La anotación @ApiMethod
se puede heredar de los 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 anotaciones @Api
y @ApiClass
, si varios métodos que se sobrescriben entre sí tienen anotaciones @ApiMethod
, se pueden sobrescribir propiedades individuales. 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
ni 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 conversación anterior, en la siguiente tabla se muestran las reglas de herencia y el orden de precedencia.
Anotación o herencia | Regla |
---|---|
@Api |
Debe ser idéntico en todas las clases. |
@ApiClass |
Se especifica para una clase con el fin de anular las propiedades de @Api . |
Herencia de Java | La clase hereda @Api y @ApiClass de la clase base. |
@ApiReference |
Class hereda @Api y @ApiClass de la clase a la que se hace referencia. |
Usar @ApiReference en una clase (Java) que hereda de una clase base |
La clase hereda @Api y @ApiClass de la clase a la que se hace referencia, no de la clase base. |
Casos de uso habituales de la herencia de anotaciones
A continuación se muestran ejemplos de los casos prácticos habituales 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 { … }
En el caso de las APIs 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, sigue estos pasos:
@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;
}
}
donde someMethod
puede devolver respuestas predeterminadas, evitar llamadas con efectos secundarios, omitir una solicitud de red o de almacén de datos, etc.
Añadir las clases a web.xml
Después de anotar las clases, debes añadirlas al archivo web.xml
. En el siguiente ejemplo se muestra una sola clase:
Para añadir varias clases, sigue estos pasos:
Sustituye
<param-value>com.example.skeleton.MyApi</param-value>
por el nombre de tu clase de API.Añade cada clase dentro del mismo campo
<param-value>
separada por una coma. Por ejemplo:<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>