단일 API가 특히 복잡한 경우, 여러 자바 클래스에서 이를 구현해야 할 수 있습니다. 동일 API를 여러 클래스 부분으로 만들려면 다음을 수행해야 합니다.
- 각 클래스의
@Api
주석에서name
및version
문자열을 동일하게 지정합니다. - 클래스 API를
web.xml
에서 쉼표로 구분된 목록으로 추가합니다.
예를 들어 다음 두 개의 클래스는 모두 tictactoe
API에 포함됩니다.
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
API 구성은 @Api
주석 속성을 통해 지정됩니다.
하지만 동일 API에 여러 클래스가 있는 경우에는 단순히 각 클래스의 @Api
주석에서 동일한 name
및 version
문자열을 사용하는 것 외에도 @Api
에 대한 요구사항이 더 있습니다. 실제로 클래스의 @Api
속성에 지정된 API 구성이 조금만 달라도 백엔드 API가 작동하지 않습니다. 멀티클래스 API에서는 클래스의 @Api
속성이 조금만 달라도 API 구성이 '모호해지기' 때문에 App Engine용 Cloud Endpoints Frameworks에서 API가 작동하지 않게 됩니다.
모호하지 않은 멀티클래스 API를 만들기 위한 방법에는 몇 가지가 있습니다.
- 단일 API의 모든 클래스가 정확히 동일한
@Api
주석 속성을 갖는지 직접 확인합니다. - 자바 상속성을 통해 주석 상속성을 사용합니다.
이 상속성을 사용할 경우 단일 API의 모든 클래스가 공통의
@Api
주석이 지정된 기본 클래스로부터 동일한 API 구성을 상속합니다. - 단일 API의 모든 클래스에서
@ApiReference
주석을 통한 주석 상속성을 사용하여 각 클래스가 공통의@Api
주석이 지정된 클래스에서 동일한 API 구성을 참조하도록 합니다.
클래스 간 달라질 수 있는 속성에 @ApiClass
사용
이 기능을 사용하려면 다음과 같은 가져오기가 필요합니다.
import com.google.api.server.spi.config.ApiClass;
@Api
주석의 모든 속성은 API의 모든 클래스에서 일치해야 하지만 @ApiClass
주석을 추가로 사용하면 클래스 간에 정확히 동일할 필요가 없는 속성을 제공할 수 있습니다. 예를 들면 다음과 같습니다.
// 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 { … }
여기에서 TicTacToeA
는 허용되는 클라이언트 ID가 포함된 클라이언트 ID 허용 목록을 사용해 액세스를 제한하는 반면 TicTacToeB
는 액세스를 제한하지 않습니다.
@ApiClass
주석에서 제공되는 모든 속성은 @Api
주석에서 상응하는 속성을 갖습니다. @Api
의 상응 속성은 API 전체의 기본값으로 사용됩니다. 동일한 속성에 대해 @Api
에 지정된 API 전체 기본값이 있는 경우에는 클래스별 @ApiClass
속성이 API 전체 기본값을 재정의합니다.
다음 예시에서는 @Api
속성이 클래스별 @ApiClass
의 상응 속성에 의해 재정의되는 경우를 보여줍니다.
// 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 { … }
주석 상속성
@Api
및 @ApiClass
주석 속성은 다른 클래스로부터 상속될 수 있으며, 자바 상속성 또는 @ApiReference
상속성을 통해 개별 속성이 재정의될 수 있습니다.
자바 상속성 사용
@Api
또는 @ApiClass
주석이 지정된 다른 클래스를 확장하는 클래스는 마치 동일한 속성의 주석이 지정된 것처럼 동작합니다. 예를 들면 다음과 같습니다.
@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 { … }
주석은 인터페이스 구현이 아니라 자바 하위 클래스를 통해서만 상속됩니다. 예를 들면 다음과 같습니다.
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
따라서 프레임워크 주석에 대해서는 어떠한 종류의 다중 상속성도 지원되지 않습니다.
상속성은 @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 { … }
여기서 TicTacToeBoards
는 BoardsBase
로부터 resource
속성 값 boards
를 상속하므로 해당 클래스의 @Api
주석에 포함된 resource
속성 설정(scores
)이 재정의됩니다. 어떤 클래스의 @Api
주석에 resource 속성이 지정되었으면 모든 클래스가 @Api
주석에서 동일한 설정을 지정해야 합니다. 이러한 상속성 기술로 @Api
속성을 재정의할 수 있습니다.
@ApiReference
상속성 사용
이 기능을 사용하려면 다음과 같은 가져오기가 필요합니다.
import com.google.api.server.spi.config.ApiReference;
@ApiReference
주석은 주석 상속성을 지정하기 위한 또 다른 방법을 제공합니다. @ApiReference
를 사용해 @Api
또는 @ApiClass
주석이 있는 다른 클래스를 지정하는 클래스는 마치 동일한 속성의 주석이 지정된 것처럼 동작합니다. 예를 들면 다음과 같습니다.
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA behaves as if it has the same @Api annotation as TicTacToeBase
@ApiReference(TicTacToeBase.class)
class TicTacToeA { … }
자바 상속성과 @ApiReference
를 모두 사용하는 경우 주석 상속은 @ApiReference
주석을 통해서만 이루어집니다. 자바 상속성을 통해 상속되는 클래스의 @Api
및 @ApiClass
주석은 무시됩니다. 예를 들면 다음과 같습니다.
@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 { … }
상속된 구성 재정의
자바 상속성을 사용해 구성을 상속하든, 혹은 @ApiReference
를 사용해 구성을 상속하든 상관없이 새로운 @Api
또는 @ApiClass
주석을 사용해 상속된 구성을 재정의할 수 있습니다. 새로운 주석에 지정된 구성 속성만 재정의됩니다. 지정되지 않은 속성은 계속 상속됩니다.
예를 들면 다음과 같습니다.
@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 { … }
상속성 재정의는 @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 { … }
또한 @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 { … }
@ApiMethod
주석 상속
@ApiMethod
주석은 재정의된 메서드로부터 상속될 수 있습니다. 예를 들면 다음과 같습니다.
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) { … }
}
@Api
및 @ApiClass
주석 상속성과 마찬가지로, 서로를 재정의하는 여러 메서드에 @ApiMethod
주석이 포함된 경우 개별 속성을 재정의할 수 있습니다. 예를 들면 다음과 같습니다.
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) { … }
}
메서드의 경우 @ApiReference
주석 또는 그에 상응하는 주석이 없으므로 @ApiMethod
는 항상 @ApiReference
가 아니라 자바 상속성을 통해 상속됩니다.
상속성 및 우선 순위 규칙
앞의 내용을 요약해서, 다음 테이블은 상속성 규칙과 우선 순위를 보여줍니다.
주석/상속성 | 규칙 |
---|---|
@Api |
모든 클래스에 대해 동일해야 합니다. |
@ApiClass |
특정 클래스가 @Api 속성을 재정의하도록 지정합니다. |
자바 상속성 | 클래스가 기본 클래스의 @Api 및 @ApiClass 를 상속합니다. |
@ApiReference |
클래스가 참조 클래스의 @Api 및 @ApiClass 를 상속합니다. |
기본 클래스로부터 상속하는 클래스(자바)에서 @ApiReference 사용 |
클래스가 기본 클래스로부터 상속하지 않고 참조 클래스의 @Api 및 @ApiClass 를 상속합니다. |
주석 상속성의 일반적인 사용 사례
다음은 상속성의 일반적인 사용 사례입니다.
API 버전 관리:
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
다중 클래스 API:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
동일 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;
}
}
여기서 someMethod
는 미리 결정된 응답을 반환하거나, 부작용이 있는 호출을 방지하거나, 네트워크 또는 데이터 저장소 요청을 건너뛰는 등의 작업을 수행할 수 있습니다.
web.xml
에 클래스 추가
클래스에 주석을 지정한 후에는 이를 web.xml
파일에 추가해야 합니다. 다음 예에서는 단일 클래스를 보여줍니다.
여러 클래스를 추가하려면 다음 안내를 따르세요.
<param-value>com.example.skeleton.MyApi</param-value>
를 해당하는 API 클래스 이름으로 바꿉니다.동일한
<param-value>
필드 내에 각 클래스를 쉼표로 구분해서 추가합니다. 예를 들면 다음과 같습니다.<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>