インターセプターの利用

インターセプターとは

インターセプターを用いることで、リクエスト時のHTTPリクエストヘッダーやHTTPレスポンスヘッダーに追加したり、メソッド実行時の前と後、例外発生後などに、クラスやメソッドの中身を修正することなく任意の処理を埋め込むことができます。これはspring frameworkやseasar2などで有名な、AOP(Aspect Oriented Program) のようなものです。

例えば、メソッド実行時にログ出力を行ったり、キャッシングを行ったりすることが可能となります。

インターセプターの利用方法

インターセプターを利用するには、ClientInterceptorクラスを継承して、新たなインターセプターを作成します。下記サンプルに従って説明していきます。

下記サンプルはコンソールにログを出力するもの(TraceInterceptor)です。以下のようにClientInterceptorを継承し、各メソッドをオーバーライドし、新たなインターセプターを作成します。

{import * from COM.CURL.ORB}

|| Traceインターセプター
{define-class public TraceInterceptor
{inherits ClientInterceptor}

{constructor public {default
client-filter:{proc-type {AbstractClient}:bool} =
{fn client => true}
}
{construct-super client-filter = client-filter}
}

{method protected open {register-interceptor
client:AbstractClient
}:void
{super.register-interceptor client}
}

{method protected open {build-server-url
server-url:Url
}:Url
{self.print “url is ” & server-url.full-filename}
{return {super.build-server-url server-url}}
}

{method protected open {build-orb-request-headers
headers:#HashTable
}:#HashTable
{if-non-null hs = headers then
{for v key k in hs do
{self.print k & ” ” & v}
}
}
{return {super.build-orb-request-headers headers}}
}

{method protected open {build-http-request-headers
headers:#HttpRequestHeaders
}:#HttpRequestHeaders
{if-non-null hs = headers then
{for v key k in hs do
{self.print ” ” & k & ” ” & v}
}
}
{return {HttpRequestHeaders “Content-Encoding”, “gzip”}}
}

{method protected open {handle-http-response-headers
headers:#HttpResponseHeaders
}:void
{if-non-null hs = headers then
{for v key k in hs do
{self.print ” ” & k & ” ” & v}
}
}
}

{method protected open {handle-before-request ||before-advice
method-name:String,
arguments:#FastArray
}:void
{self.print “before invoking ” & method-name}
}

{method protected open {handle-after-response ||after-returning-advice
method-name:String,
arguments:#FastArray,
return-value:#any
}:void
{self.print “after invoking ” & method-name & “, get ” & return-value}
}

{method protected open {handle-exception ||throw-advice
method-name:String,
arguments:#FastArray,
exception:Exception
}:void
{self.print “after throwing ” & exception}
}

|| — private —
{method private {print str:String}:void
{output “[TraceInterceptor] ” & str}
}
}

以下は各メソッドの説明です。

  • register-interceptor :Interceptor登録時の処理を定義できます。
  • build-server-url :サーバのURL定義する際の処理を記述できます。
  • build-orb-request-header :ORB独自リクエストヘッダーへ定義する際の処理を記述できます。(送信した情報はServletFilter内で取得InstanceManagementUtil.getRequestメソッドでInstanceManagementRequestオブジェクトを取得し、そのInstanceManagementRequest.getHeaderでヘッダー情報を取得できます。(Mapオブジェクトとして取得)
  • build-http-request-header :HTTPリクエストヘッダーへ定義する際の処理を記述できます。
  • handle-http-response-header :HTTPレスポンスヘッダーの定義を利用する際の処理を記述できます。
  • handle-before-request :メソッド実行前の処理を定義できます。
  • handle-after-response :メソッド実行後の処理を定義できます。
  • handle-exception :例外発生時の処理を定義できます。

インターセプターの登録はregisterクラスプロシージャで可能です。各サービスクラスには、インスタンスが生成された際にインターセプターが付与されます。そのため、インスタンス生成時より以前にregisterする必要があります。

{ClientInterceptor.register
|| client-filterはInterceptorをセットするクラスをフィルタリングできます。
{TraceInterceptor client-filter = {fn c => (c isa Hoge)}}
}