Ymirではリクエストされたパスの正規表現パターンと処理コンポーネント(Javaクラス)名の対応(パスマッピング)が定義されており、リクエストパスについてパターンにマッチするようなパスマッピングからコンポーネント名やアクション名が組み立てられて処理メソッドの呼び出しが行なわれます。
標準のパスマッピング
標準のパスマッピングはmapping.diconで次のように定義されています。
| パターン | Pageコンポーネント名テンプレート | アクション名テンプレート | デフォルトの返り値 | ボタンとアクションを関連付けるためのパターン | パラメータテンプレート |
|---|---|---|---|---|---|
| ^$ | _RootPage | _${method} | null | null | null |
| ^/([a-zA-Z][a-zA-Z0-9]*)\\.(html|do)$ | ${1}Page | _${method} | /${1}.html | ^_([a-zA-Z][a-zA-Z0-9]*)$ | null |
| ^/([a-zA-Z][a-zA-Z0-9]*)/([a-zA-Z][a-zA-Z0-9]*)\\.do$ | ${1}Page | _${method}_${2} | redirect:/${1}.html | null | null |
「パターン」は、リクエストパス(コンテキストパス相対)の正規表現です。例えば「/path.html」は2番目のパターンにマッチします。「/path/sub.html」は3番目のパターンにマッチします。
「Pageコンポーネント名テンプレート」は、処理メソッドを持つPageコンポーネントの名前を構築するためのテンプレートです。テンプレートには${...}形式で変数の値を埋め込むことができます。
| 変数 | 意味 |
|---|---|
| ${数値} | パス文字列のうちパターン中で括弧で囲われている部分にマッチした部分の数値番目のもの |
| ${数値u} | ${数値}を全て大文字にしたもの |
| ${数値l} | ${数値}を全て小文字にしたもの |
| ${`} | パス文字列のうちパターンにマッチした部分よりも前の部分 |
| ${&} | パス文字列のうちパターンにマッチした部分 |
| ${'} | パス文字列のうちパターンにマッチした部分よりも後ろの部分 |
| ${method} | HTTPメソッド名(全て小文字) |
| ${Method} | HTTPメソッド名(先頭だけ大文字) |
| ${METHOD} | HTTPメソッド名(全て大文字) |
例えばリクエストパスが「/path.html」である場合は実際のコンポーネント名は「pathPage」となり、Ymirはこの名前を持つコンポーネントをS2Containerから取り出してメソッド呼び出しを行ないます。
なお、PageコンポーネントはS2Containerによって自動登録されます。例えばアプリケーションのルートパッケージ名がcom.example.appである場合はcom.example.app.web.XyzPageというクラスのインスタンスがxyzPageという名前でコンポーネント登録されます。pathPageコンポーネントであればcom.example.app.web.PathPageクラスということになります。
「アクション名テンプレート」は、呼び出すメソッド(アクション)の名前を構築するためのテンプレートです。例えばリクエストパスが「/path.html」でPOSTメソッドでリクエストがあった場合は実際のアクション名は「_post」となり、YmirはpathPageコンポーネントの_postメソッドの呼び出しを行ないます。
「デフォルトの返り値」は、アクションの返り値から構築したレスポンスオブジェクトのタイプがPASSTHROUGHであった場合に返り値として使われる文字列のテンプレートです。具体的には、このテンプレートから構築された文字列がアクションの返り値であるとみなされます。例えばリクエストパスが「/path/sub.html」でアクションの返り値がPASSTHROUGHタイプのレスポンスであった場合、"redirect:/path.html"が返り値とみなされます。なおデフォルトの返り値がnullである場合はそのままPASSTHROUGHがレスポンスとして使われます。
「ボタンとアクションを関連付けるためのパターン」は、複数submitボタンを持つようなフォームでボタン毎に呼び出すアクションを変える際の、アクション名を構築するためのパターンです。詳しくは後述します。
「パラメータテンプレート」は、パスからパラメータを取り出すためのルールです。詳しくは後述します。
ボタンとアクションの関連付け
複数submitボタンを持つようなフォームで、押されたボタン毎に呼び出すアクションを変えたい場合があります。その場合は、パスマッピングの「ボタンとアクションを関連付けるためのパターン」にパターン文字列を指定します。nullを指定した場合は、どのボタンが押されても呼び出されるアクションは同一となります。
アクションとボタンの関連付けは以下のように行なわれます。
Pageクラスのメソッドでアクション名で始まるもののうち、メソッド名からアクション名の部分を取り除いた文字列がパターン文字列にマッチするメソッドについて、パターン文字列中の「()」の部分にマッチした文字列がボタン名とみなされ、そのボタンが押された場合にこのメソッドが実行されることになります。
例えばパターン文字列が「^_([a-zA-Z][a-zA-Z0-9]*)$」でアクション名が「_post」の時、Pageクラスが「_post_search」という名前のメソッドを持っている場合、「_search」が「^_([a-zA-Z][a-zA-Z0-9]*)$」にマッチし、パターン文字列中の「()」の部分には「search」がマッチするので、名前が「search」であるボタンが押された際には「_post_search」メソッドがアクションとして呼び出されることになります。
ボタンが押された際にパラメータを渡すこともできます。上記の例でボタン名を「search[1][cond]」のように「[]」でパラメータをつけた形にしておくと、パラメータが適宜型変換されてアクションメソッド「_post_search」の引数として渡されます。
pathInfo
パスマッピングのpathInfoTemplateプロパティにpathInfoテンプレートを指定することで、パスの一部をpathInfo情報として取り出すことができます。
pathInfoテンプレートは他のテンプレートと同様、${...}形式の変数が埋め込まれた文字列です。例えばパスのパターンとして「^/([^/]+)」、pathInfoテンプレートとして「${'}」が指定されているケースで、リクエストパスが「/download/file.pdf」である場合、pathInfoは「/file.pdf」となります。
pathInfo情報はRequestオブジェクトから取り出したorg.seasar.ymir.DispatchオブジェクトからDispatch#getPathInfo()で取り出すことができます。
パスからのパラメータの取り出し
パスマッピングにパラメータテンプレートを指定することで、パス中の任意の部分文字列をパラメータとして取り出すことができます。このパラメータをURIパラメータと呼びます。
パラメータテンプレートは「パラメータ名=${...}」形式の文字列です。パラメータ名を複数並べる場合は「;」で区切ります。同名のパラメータ名を並べることもできます。その場合はパラメータの値が複数になります。
例えばパスのパターンとして「^/article/([^/]+)/([^/]+).html」、パラメータテンプレートとして「category=${1};id=${2}」が指定されているケースで、リクエストパスが「/article/computer/15.html」である場合、パラメータ「category」の値として「computer」、「id」の値として「15」が取り出されます。
URIパラメータは通常のリクエストパラメータとマージされてRequestオブジェクトにセットされます。従って、例えば/index.html?param=aaaというパスにアクセスした場合でURIパラメータとしてparam=bbbが取り出された場合、Request#getParameterValues("param")の返り値は"aaa"と"bbb"になります(順序は不定です)。
URIパラメータはリクエストパラメータとマージされますので、リクエストパラメータと同様Pageオブジェクトに自動的にインジェクトされます。
パスマッピングのカスタマイズ
パスマッピングは上書き定義することでアプリケーションごとに変更することができます。変更したい場合はパスマッピング定義をmapping+.diconというファイルに書いて下さい。通常はmapping.diconをmapping+.diconという名前でコピーして、適宜パスマッピング定義を編集するようにすると良いでしょう。
パスマッピングのコンポーネント定義は例えば以下のように書きます:
<component class="org.seasar.ymir.impl.PathMappingImpl">
<arg>"^/([a-zA-Z][a-zA-Z0-9]*)\\.(html|do)$"</arg>
<arg>"${1}Page"</arg>
<arg>"_${method}"</arg>
<arg>""</arg>
<arg>"/${1}.html"</arg>
<arg>"^_([a-zA-Z][a-zA-Z0-9]*)$"</arg>
<arg>null</arg>
</component>
第1引数から順に「パターン」「Pageコンポーネント名テンプレート」「アクション名テンプレート」「pathInfoテンプレート」「デフォルトの返り値」「ボタンとアクションを関連付けるためのパターン」「パラメータテンプレート」となります。引数の詳細や他の指定方法についてはPathMappingImplクラスの定義を参照して下さい。