|
BestPractice
ja, en T2を使う上でのベストプラクティスをまとめてみました. Programming@DefaultをPageクラスに必ず1つつけるT2のプログラミングモデルでは、Pageクラスでいずれかのアクションメソッドが処理されるはずです. しかし、これらが処理されない場合に別のPageクラスを探索します. そのため、確実に特定のPageクラスで処理させる場合には、@Defaultをつけたデフォルトメソッドを作成しておきます. 以下のようなコードイメージになります.この例では、fugaメソッドとmogeメソッドの条件にマッチしない場合、indexメソッドが呼ばれます. @Page("/hoge")
public class HogePage {
@Default
public Navigation index(WebContext context) {
return Redirect.to("/jsp/add.jsp");
}
@POST
@ActionParam
public Navigation fuga(WebContext context) {
...
}
@GET
@ActionPath
public Navigation moge(HttpServletRequest req) {
...
}
Pageクラスでオーバーロードメソッドは避けるPageクラスでオーバーロードメソッドは避けるべきです.T2ではアクションメソッドのオーバーロードメソッドは推奨していません. なぜならユーザからのリクエストの受け口であるアクションメソッドは出来る限り明示的でわかりやすくする必要があるからです. そのため、オーバーロードメソッドで対応するのではなく、より適切なメソッド名をつけてください. このことが開発トータルで見たときの保守性はあげます. Pageクラスの管理方法を統一するPageクラスを管理する方法は大きく分けて最初からDIコンテナに全て管理させる方法と、T2のeagerloadオプションを使って、 稼働時にDIコンテナに登録させる方法とがあります.最初からDIコンテナに登録させる方法は、例えばSpringを使う場合には、設定ファイルである applicationContext.xmlにT2のPageクラスを記述してしまうといった具合です. 一方eagerloadオプションを使えば、稼働した初期化時にT2の方からDIコンテナに登録にいくので、 設定を記述しておく必要がないので、開発時などには便利です. どちらにせよ、アプリケーション全体でPageクラスを管理する方法は統一しておいてください. オススメはお使いのDIコンテナにきちんと記述して管理させる方法です. @Formを使って変換する場合には、ErrorInfoも引数に記載する@FormはT2が送信されてきたフォーム内容をPOJOに変換する機能です. しかし、このままだとT2がPOJOに変換した際にエラーが発生したかどうかを知ることが出来ません. そこで、ErrorInfoを併用すると、フレームワーク内部で変換したときにエラーが発生したかどうかを知ることが出来ます. @Formを使う場合、以下のようなコーディングを推奨します. @POST
@ActionParam
public Navigation addWithForm(@Form AddForm dto, ErrorInfo errorInfo) {
......
}Configuration適切なDIコンテナを使うT2に限った話ではありませんが、DIコンテナは使う事を検討に値するフレームワークです. 特にT2ではDIコンテナ連携機能が準備されているため、ぜひ利用を検討してみてください. その際に、プロジェクトにより適したDIコンテナを使ってください. 例えば以下のような点を検討すると良いでしょう.
T2とDIコンテナの連携の仕方は、フレームワーク連携を参照してください. Debuggingログに出力された情報をよく見るT2では以下のような手順でPageインスタンスのアクションメソッドを探索し、実行します. + 送信されてきたURLから該当のPageインスタンス候補を探し、1つづつ試していきます. + Pageインスタンスの中から、対象となるアクションメソッドを探し出します. + アクションメソッドを実行し、その結果をNavigationのインスタンスでもらいます. このようなポイントのところは、ログで全て出力するようにしています. まずは、上記のポイントが自分の想定どおり動いているかを確認してみましょう. ログは下記のようになっています(適宜見やすいように改行いれています). 23:37:11.731 [HttpProcessor:init0] INFO o.t.t2.action.impl.ActionInvokerImpl - リクエストを処理するPageクラスを検出しました。(Pageクラス名:HelloPage, IndexPage). 23:37:11 [HttpProcessor:init0] INFO o.t.t2.action.impl.ActionInvokerImpl - リクエストを処理するPageクラスを検出しました。(Pageクラス名:HelloPage, IndexPage). 23:37:11.732 [HttpProcessor:init0] DEBUG o.t.t.a.impl.ActionInvokerFilterImpl org.t2framework.t2.lifecycle - URL(/t2-samples/hello)に対して、アクションメソッド(HelloPage#index(org.t2framework.t2.contexts.impl.RequestImpl@775121))を実行します. 23:37:11 [HttpProcessor:init0] DEBUG o.t.t.a.impl.ActionInvokerFilterImpl - URL(/t2-samples/hello)に対して、アクションメソッド(HelloPage#index(org.t2framework.t2.contexts.impl.RequestImpl@775121))を実行します. 23:37:11.732 [HttpProcessor:init0] DEBUG o.t.t.a.impl.ActionInvokerFilterImpl org.t2framework.t2.lifecycle - URL(/t2-samples/hello)に対して、アクションメソッド(HelloPage#index(org.t2framework.t2.contexts.impl.RequestImpl@775121))を実行しました. 23:37:11 [HttpProcessor:init0] DEBUG o.t.t.a.impl.ActionInvokerFilterImpl - URL(/t2-samples/hello)に対して、アクションメソッド(HelloPage#index(org.t2framework.t2.contexts.impl.RequestImpl@775121))を実行しました. 23:37:11.733 [HttpProcessor:init0] DEBUG org.t2framework.t2.filter.T2Filter org.t2framework.t2.lifecycle - Navigation(org.t2framework.t2.navigation.Forward@16f70a4)が見つかりました. 23:37:11 [HttpProcessor:init0] DEBUG org.t2framework.t2.filter.T2Filter - Navigation(org.t2framework.t2.navigation.Forward@16f70a4)が見つかりました. この例では、以下のようなことがわかります.
大きな動きはこのようにデバッグしやすくなっています. ログ出力を細かく制御するT2のロギングはコアライブラリとして、slf4j/logbackというライブラリを使用しています. このライブラリはログ出力を細かく制御する仕組みがあり、それをマーカと言います. T2の重要なログはこのマーカを使って制御する事が可能です. T2のマーカは下記のように定義されています.
マーカの制御には、slf4j/logbackロギングの設定ファイルで指定します. 例えば以下の例では、T2のDESIGN関連のログを出力するようにしています. <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.design</Marker> <OnMatch>ACCEPT</OnMatch> </turboFilter> T2のデフォルトの設定はt2-filters.xmlとしてjarファイルに同梱されているので、以下のようにincludeして使う事が可能です. <configuration debug="true"> <include resource="t2-filters.xml" /> ...... t2-filters.xmlは下記のようになっています. <included> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2</Marker> <OnMatch>ACCEPT</OnMatch> </turboFilter> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.design</Marker> <OnMatch>ACCEPT</OnMatch> </turboFilter> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.boundary</Marker> <OnMatch>ACCEPT</OnMatch> </turboFilter> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.lifecycle</Marker> <OnMatch>ACCEPT</OnMatch> </turboFilter> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.detail</Marker> <OnMatch>DENY</OnMatch> </turboFilter> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>org.t2framework.t2.profile</Marker> <OnMatch>DENY</OnMatch> </turboFilter> </included>
TOPに戻る | |||||||||||||||||||