Pageコンポーネントのアクション呼び出しの後にどのようなHTTPレスポンスがクライアントに返されるかは、アクションの返り値によって決定されます。
具体的には、アクションの返り値型に対応したResponseConstructorのconstructResponseメソッドを呼び出して得られるのResponseオブジェクトからHTTPレスポンスが構築されます。
Responseオブジェクト
Responseオブジェクトは、HTTPレスポンスを抽象化したオブジェクトです。
Responseオブジェクトはタイプを持っています。タイプは以下のいずれかです。
- PASSTHROUGH
- Ymirは何もせず、次のサーブレットフィルタチェインに処理を委譲する
- FORWARD
- Responseオブジェクトが指すパスに処理をフォワードする
- REDIRECT
- Responseオブジェクトが指すパスに処理をリダイレクトする
- SELF_CONTAINED
- Responseオブジェクトが持つStringまたはInputStreamの内容をそのままレスポンスとして出力する
- VOID
- 何もしない(次のサーブレットフィルタチェインにも処理を委譲しない)
ResponseConstructor
ResponseConstructorは、Pageコンポーネントとアクションの返り値からResponseオブジェクトを構築するためのオブジェクトで、アクションの返り値型に関連付けられています。
Pageコンポーネントのアクション呼び出しの後、Ymirはアクションの返り値型に対応したResponseConstructorのconstructResponseメソッドを呼び出してResponseオブジェクトを構築します。
例えばPageコンポーネントの_postメソッドの返り値型がjava.lang.Objectで実際の返り値が"/path/to/page"という文字列である場合、Ymirはjava.lang.Objectに関連付けられているResponseConstructorを検索し、constructResponseメソッドを呼び出します。
Ymirにはデフォルトで以下のResponseConstructorが登録されています。
返り値型 | ResponseConstructor |
---|---|
java.io.InputStream | InputStreamResponseConstructor |
java.lang.Object | ObjectResponseConstructor |
org.seasar.ymir.Path | PathResponseConstructor |
org.seasar.ymir.Response | ResponseResponseConstructor |
java.lang.String | StringResponseConstructor |
void | VoidResponseConstructor |
- InputStreamResponseConstructor
-
アクションの返り値であるInputStreamがそのままHTTPレスポンスとして出力されます。
返り値がnullである場合は何も出力されません。
- ObjectResponseConstructor
-
返り値の実際の型からResponseConstructorが検索され、見つかったものを使ってHTTPレスポンスが構築されます。例えばアクションの返り値型がObjectで実際の返り値がStringの場合はStringResponseConstructorを使ってレスポンスが構築されます。
返り値の実際の型CからResponseConstructorを検索する手順は以下のとおりです。
- Cに対応するものがあればそれを使う
- なければ、Cのスーパークラスに対応するものがあればそれを使う
- Cのどのスーパークラスに対応するものもなければ、Cが実装するインタフェースIに対応するものがあればそれを使う。なければ、Iのスーパーインタフェースに対応するものがあればそれを使う
- Cが実装するどのインタフェースに対応するものもなければ、Cのスーパークラスが実装するインタフェースI'に対応するものがあればそれを使う。なければ、I'のスーパーインタフェースに対応するものがあればそれを使う
- なければ、Stringに関連付けられたものを使う。この時は、返り値についてtoString()を呼び出した結果を返り値とみなしてconstructResponseの呼び出しを行なう
- PathResponseConstructor
-
アクションの返り値であるPathオブジェクトが指す先にリダイレクトします。
返り値がnullである場合は何も出力されません。
- ResponseResponseConstructor
-
アクションの返り値であるResponseオブジェクトをそのまま使ってHTTPレスポンスが構築されます。
返り値がnullである場合は何も出力されません。
- StringResponseConstructor
-
アクションの返り値である文字列の内容に従ってHTTPレスポンスが構築されます。処理の詳細は「返り値が文字列の場合の処理」を参照して下さい。
返り値がnullである場合は何も出力されません。
- VoidResponseConstructor
-
レスポンスの構築処理は次のサーブレットフィルタチェインに委譲されます。
[Ymir-1.0.3以降] ただしHttpServletResponse#isCommitted()がtrueの場合は何もしません。
返り値が文字列の場合の処理
アクションの返り値が文字列である場合、レスポンスの構築にはStringResponseConstructorが使われます。
StringResponseConstructorでは、まず返り値の文字列を最初に見つかった「:」の前後で分割します。前者を「スキーム」、後者を「パス」と呼びます。レスポンスはスキームに関連付けられたStrategyに従って構築されます。文字列が:を含まない場合は、スキームは「forward」、パスは文字列全体であるとみなされます。スキームの種類と構築されるレスポンスの詳細は以下のとおりです。
- forward
- パスがフォワード先のコンテキスト相対パスとみなされ、フォワード処理が行なわれます。
- passthrough
- レスポンスの構築処理は次のサーブレットフィルタチェインに委譲されます。パスは無視されます。
- redirect
-
パスがリダイレクト先のパスとみなされ、リダイレクト処理が行なわれます。
「/」で始まるパスはコンテキスト相対パスとみなされます。パスからリクエストパラメータ等を除いた部分が空文字列である場合もコンテキスト相対パスとみなされます。
パスからリクエストパラメータ等を除いた部分が「.」である場合は現在リクエストされているパス自身とみなされます。
それ以外はそのままURLとみなされます。
app.propertiesのcore.response.strategy.richPathExpressionAvailableプロパティがtrueであるかこのプロパティの指定がない場合、以下の拡張表現が有効になります。
- パスの末尾に「(a,b)」のように記述すると、Pageコンポーネントのプロパティaとbの値がリクエストパラメータとして連結されます。例えばプロパティaの値が"A"でプロパティbの値が"B"である場合、/path/to/page(a,b)の実際のパスは/path/to/page?a=A&b=Bとなります。
- リクエストパラメータの部分を「?a=${a}&b=${b}」のように記述すると、${...}``の部分がPageコンポーネントのプロパティの値で置換されます。例えばプロパティaの値が"A"でプロパティbの値が"B"である場合、/path/to/page?a=${a}&b=${b}の実際のパスは/path/to/page?a=A&b=Bとなります。
- リクエストパラメータの部分を「?a&b」のように値をつけずに記述すると、Pageコンポーネントのプロパティの値が埋め込まれます。例えばプロパティaの値が"A"でプロパティbの値が"B"である場合、/path/to/page?a&b``の実際のパスは/path/to/page?a=A&b=Bとなります。
- proceed
- redirectと基本的には同じですが、内部的にはフォワード処理が行なわれます。通常のフォワード処理との違いは、フォワード前のリクエストパラメータがフォワード先に引き継がれないことです。例えば /aaa.html?a=1 というパスの処理の後にproceedによって /bbb.html?b=1 に遷移した場合、BbbPageクラスにはリクエストパラメータとしてbだけが渡され、aは渡されません(ただし、直接HttpServletRequestからリクエストパラメータを取得するとaが取得できます)。また、フォワード後のHTTPメソッドはフォワード前のHTTPメソッドによらずGETと見なされます(ただし、直接HttpServletRequestからHTTPメソッドを取得するとフォワード前のHTTPメソッドが取得できます)。このため、基本的にはリダイレクトの置き換えとして使用することができます。携帯アプリケーションを作成する場合など、Post Redirect Getパターンは使いたいがリダイレクトは極力しないようにしたい場合にはredirectの代わりにproceedを使うと良いでしょう。
- resource
-
パスがリソースパスとみなされ、コンテキストクラスローダからリソースが取得されてバイナリデータとして返されます。
リソースのコンテントタイプは、web.xmlに定義されているmime-typeのうちパス名の拡張子に対応するエントリから決定されてレスポンスヘッダに設定されます。なお、コンテントタイプがtextである場合はcharset=UTF-8が自動的に付与されますので、テキストリソースの文字エンコーディングはUTF-8である必要があります。
- content
-
パスがコンテンツ文字列とみなされ、そのままレスポンスとして返されます。
コンテントタイプは、デフォルトではtext/html; charset=UTF-8になります。コンテントタイプを明示的に指定したい場合は、コンテンツ文字列の先頭に「:」区切りで指定して下さい。
例:
content:text/plain; charset=UTF-8:こんにちは!
このように、「:」がコンテントタイプを指定するための区切り文字と認識されますので、誤認識を避けるために、コンテンツ文字列に「:」が含まれるかもしれない場合は明示的にコンテントタイプを指定するようにして下さい。