リクエスト処理
リクエストハンドラー
リクエストハンドラーは、受け取った1つ以上のタイプのリクエストを処理します。
リクエストハンドラーを作成するには、RequestHandler
インターフェースまたは型付けされたリクエストハンドラーインターフェースを実装します。どちらも次の2つのメソッドで構成されます。
canHandle
。SDKによって呼び出され、指定されたハンドラーが受け取ったリクエストを処理できるかどうかを判断します。ハンドラーがリクエストを処理できる場合はtrue、できない場合はfalseを返します。受信するリクエストのタイプやパラメーター、スキルのアトリビュートなど、この判断を行うための条件を柔軟に選択できます。handle
。リクエストハンドラーを呼び出す時にSDKによって呼び出されます。このメソッドには、ハンドラーのリクエスト処理ロジックが含まれており、オプションのResponse
を返します。
汎用のリクエストハンドラー
汎用のRequestHandler
インターフェースは、複数のリクエストタイプを処理する場合に使用でき、さまざまなリクエストタイプで類似のコードパスがある場合に役立ちます。
以下は、受信したSkillEnabledRequest
またはSkillDisabledRequest
を処理するように設定されたリクエストハンドラーの例です。
public class SkillEventsHandler implements RequestHandler {
@Override
public boolean canHandle(HandlerInput input) {
return input.getRequest() instanceof SkillEnabledRequest
|| input.getRequest() instanceof SkillDisabledRequest;
}
@Override
public Optional<Response> handle(HandlerInput input) {
logger.info("スキルイベントが受信されました");
if (input.getRequest() instanceof SkillEnabledRequest) {
SkillEnabledRequest request = (SkillEnabledRequest) input.getRequest();
logger.info("ユーザーが{}にスキルを有効にしました", request.getEventCreationTime());
}
if (input.getRequest() instanceof SkillDisabledRequest) {
SkillDisabledRequest request = (SkillDisabledRequest) input.getRequest();
logger.info("ユーザーが{}にスキルを無効にしました", request.getEventCreationTime());
}
}
}
型付けされたリクエストハンドラー
SDKがサポートする各リクエストタイプ(IntentRequest、LaunchRequest、SkillEnabledRequestなど)に型付けされたリクエストハンドラーインターフェースを利用でき、特定のリクエストタイプのハンドラーを作成するための型安全な方法が提供されます。汎用のRequestHandler
インターフェースを使用する場合は、型を確認し、特定のリクエストの型に対して機能するようにキャストする必要があります。型付けされたハンドラーではその必要はなく、ハンドラーが型の確認処理を行います。たとえばLaunchRequestHandler
インターフェースを実装するハンドラーは、受信リクエストがLaunchRequest
の場合のみ呼び出されます。
現在利用可能な型固有のリクエストハンドラーのリストは、こちらを参照してください。
以下は、HelloWorldIntent
を処理するよう設定されたリクエストハンドラーの例です。このように、インテントリクエストを処理する場合、ハンドラーはIntentRequestHandler
インターフェースを実装します。
public class HelloWorldIntentHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput input, IntentRequest intentRequest) {
return intentRequest.getIntent().getName().equals("HelloWorldIntent");
}
@Override
public Optional<Response> handle(HandlerInput input, IntentRequest intentRequest) {
String speechText = "こんにちは";
Intent intent = intentRequest.getIntent();
String intentName = intent.getName();
return input.getResponseBuilder()
.withSpeech(speechText)
.withSimpleCard(intentName, speechText)
.build();
}
}
このタイプのハンドラーは、受信リクエストがIntentRequest
である場合のみ呼び出されます。ハンドラーのcanHandle
メソッドは、リクエストのインテント名を確認し、インテント名がHelloWorldIntent
の場合はtrueを返すよう設定されています。handle
メソッドで基本の「こんにちは」という応答が生成され、返されます。canHandle
の条件を変更すると、たとえばインテントのスロット値を検査することでハンドラーをさらにきめ細かくしたり、すべてのIntentRequest
に対してtrueを返してハンドラーをより汎用的にしたりすることができます。
CanHandle述部
SDKには、インテント名、スロット値、アトリビュートなど共通の条件を簡単に評価できる、プリビルドされた一連のcanHandle述部が含まれています。これにより、複雑なcanHandle
条件を持つロジックの作成が、より簡単にシンプルに作成できます。SDKで提供される利用可能な述部のリストは、こちらを参照してください。
たとえば、上記のHelloWorldインテントのサンプルハンドラーは、述部を使用してCanHandle条件をシンプルにできます。
@Override
public boolean canHandle(HandlerInput input, IntentRequest intentRequest) {
return input.matches(Predicates.intentName("HelloWorldIntent"));
}
同様に、SkillEnabledRequest
用またはSkillDisabledRequest
用のハンドラーを示す汎用RequestHandlerの例は、次のようになります。
@Override
public boolean canHandle(HandlerInput input) {
return input.matches(Predicates.requestType(SkillEnabledRequest.class)
.or(Predicates.requestType(SkillDisabledRequest.class)));
}
ハンドラーの処理順序
SDKは、リクエストハンドラーで、スキルビルダーに提供した順序でcanHandle
メソッドを呼び出します。同じリクエストタイプ用の複数のハンドラー(IntentRequestHandler
を実装する複数のハンドラーなど)を含め、スキルには必要な数のリクエストハンドラーを実装することができます。この場合、SDKは登録された順序でこれらのハンドラーにアクセスし、canHandle
メソッドで最初にtrue
を返したハンドラーを利用します。
return Skills.standard()
.addHandlers(new FooHandler(), new BarHandler(), new BazHandler())
.build();
この例では、SDKが以下の順序でリクエストハンドラーを呼び出します。
- FooHandler
- BarHandler
- BazHandler
SDKは、指定されたリクエストを処理できる最初のハンドラーを常に選択します。この例では、FooHandler
とBarHandler
の両方が特定のリクエストを処理できる場合、常にFooHandler
が呼び出されます。リクエストハンドラーのデザインや登録を行う際には、この点を考慮に入れてください。
リクエストと応答のインターセプター
SDKは、RequestHandler
の実行前と実行後に実行するリクエストと応答のインターセプターをサポートします。リクエストインターセプターはRequestInterceptor
インターフェースを使用して、応答インターセプターはResponseInterceptor
インターフェースを使用して実装できます。
どちらのインターセプターインターフェースも、戻り値の型がvoidであるprocess
メソッドを1つ実行します。リクエストのインターセプターはHandlerInput
インスタンスにアクセスでき、応答のインターセプターはHandlerInput
と、RequestHandler
によって生成されるOptional<Response>
にアクセスできます。
public class PersistenceSavingResponseInterceptor implements ResponseInterceptor {
@Override
public void process(HandlerInput input, Optional<Response> output) {
input.getAttributesManager().savePersistentAttributes();
}
}
リクエストのインターセプターは、受け取るリクエストのリクエストハンドラーが実行される直前に呼び出されます。リクエストアトリビュートは、リクエストのインターセプターがリクエストハンドラーにデータやエンティティを渡す方法を提供します。
応答のインターセプターは、リクエストハンドラーが実行された直後に呼び出されます。応答のインターセプターはリクエストハンドラーを実行して生成される出力結果にアクセスできるため、応答のサニタイズや検証といったタスクに適しています。
以下の例は、スキル
ビルダーのSDKを使ってインターセプターを登録する方法を示しています。
return Skills.standard()
.addHandlers(new FooHandler(), new BarHandler(), new BazHandler())
.addRequestInterceptors(new FooRequestInterceptor())
.addResponseInterceptors(new BarResponseInterceptor())
.build();
例外ハンドラー
例外ハンドラーはリクエストハンドラーに似ていますが、リクエストではなく1つまたは複数のタイプの例外を処理します。リクエストの処理中に未処理の例外がスローされると、SDKが例外ハンドラーを呼び出します。
すべての例外ハンドラーは、ExceptionHandlerインターフェースを実装する必要があります。このインターフェースは以下の2つのメソッドで構成されます。
canHandle
は、SDKによって呼び出され、指定されたハンドラーが例外を処理できるかどうかを判断します。ハンドラーが例外を処理できる場合はtrue、できない場合はfalseを返します。catch-allハンドラーは常にtrueを返すだけで簡単に導入できます。handle
は、例外ハンドラーを呼び出すときにSDKによって呼び出されます。このメソッドには、例外処理ロジックがすべて含まれ、オプションでResponse
を含む場合がある出力を返します。
以下は、AskSdkException
タイプの例外を処理するよう設定された例外ハンドラーの例です。
public class MyExecptionHandler implements ExceptionHandler {
@Override
public boolean canHandle(HandlerInput input, Throwable throwable) {
return throwable instanceof AskSdkException;
}
@Override
public HandlerOutput handle(HandlerInput input, Throwable throwable) {
return input.getResponseBuilder()
.withSpeech("リクエストの処理中にエラーが発生しました。後でもう一度お試しください。")
.build();
}
}
ハンドラーのcanHandle
メソッドは、受け取る例外がAskSdkException
のインスタンスである場合にtrueを返します。handleメソッドは、ユーザーに正常なエラー応答を返します。
例外ハンドラーはリクエストハンドラーと同様に実行され、SDKはSkill
で指定した順序でハンドラーにアクセスします。
ハンドラー入力
リクエストハンドラー、リクエストと応答のインターセプター、例外ハンドラーにはすべて、呼び出し時にHandlerInputインスタンスが渡されます。このクラスには、リクエスト処理に有効な各種エンティティが含まれます。以下はその例です。
- RequestEnvelope: 受信する
Request
と他のコンテキストが含まれます。 - AttributesManager: リクエスト、セッション、永続アトリビュートへのアクセスを提供します。
- ServiceClientFactory: Alexa APIの呼び出しが可能なサービスクライアントを構築します。
- ResponseBuilder: 応答を作成するのを支援します。
- Context: ホストコンテナが渡すオプションのcontextオブジェクトを提供します。たとえば、AWS Lambdaで実行されるスキルの場合は、AWS Lambda関数のcontextオブジェクトになります。