ページクラス

リクエストパラメータのバインド

Click Frameworkは標準でページクラスのpublicフィールドに同じ名前のリクエストパラメータをバインドする機能を備えています。 しかし、S2ClickのページにはDI用のpublicフィールドも存在するため、リクエストパラメータによるDI用フィールドの上書きを防ぐため、 リクエストパラメータの自動バインド機能は利用できません。

代替手段として、@Requestアノテーションを付与したpublicフィールドにリクエストパラメータをバインドすることができます。 デフォルトではフィールド名と同じ名前のリクエストパラメータがバインドされますが、 @Requestアノテーションのパラメータによって別の名前のリクエストパラメータをバインドすることもできます。

また、@Requestアノテーションにrequired=trueの指定を追加することで、パラメータの必須チェックを自動的に行うことができます (必須パラメータが設定されなかった場合にはRuntimeExceptionが発生します)。

public class HelloPage extends Page {

  /** idというリクエストパラメータをバインド */
  @Request
  public String id;

  /** articleというリクエストパラメータをバインド(必須) */
  @Request(name="article", required=true)
  public String articleId;

}

ページクラスの基底クラス

S2ClickPage

S2ClickはAjaxやファイルダウンロードでの利用を想定し、ページクラスの抽象基底クラスを提供しています。 Ajaxやファイルダウンロード機能を使用するページクラスはorg.seasar.s2click.S2ClickPageを継承して実装します。 S2ClickPageには以下のようなメソッドが用意されており、サブクラスではこれらのメソッドを呼び出すことでJSONやHTML、ファイルなどを返却することができます。

メソッド名 説明
renderJSON(Object obj) 引数で渡したオブジェクトをJSONとしてレスポンスにレンダリングします。
renderHTML(String html) 引数で渡した文字列をHTMLとしてレスポンスにレンダリングします。
renderFile(String fileName, InputStream in) 引数で渡したファイル名と入力ストリームの内容をレスポンスにレンダリングします。
renderResponse(String contentType, InputStream in) コンテンツタイプを指定して入力ストリームの内容をレスポンスにレンダリングします。

アノテーションによるパスの指定

@Pathアノテーションで任意のパスにページクラスをマッピングすることができます。 対応するVelocityテンプレートが存在しないページクラスのパスを指定する場合に使用します。

@Path("/controls.htm")
public class ControlsPage extends LayoutPage {
  ...
} 

@UrlPatternアノテーションをページクラスに付与すると、ページに任意のエイリアスを指定することができます。 これはApacheのmod_rewriteのように動作します。URLパターンで指定したパスの一部をリクエストパラメータにマッピングすることもできます。

@UrlPattern("/user/select/{userId}")
public class UrlPatternPage extends LayoutPage {

  // リクエストパスの{userId}に一致した部分がセットされます
  @Request
  public String userId;

} 

Ajaxの実装例

JSONによるAjaxを実現するページクラスの実装例を以下に示します。

public class AjaxPage extends S2ClickPage {

  public AjaxPage(){
    AjaxButton button = new AjaxButton("button", "書籍情報を取得", this, "getAllBooks");
    button.addAjaxHandler(AjaxRequestButton.ON_COMPLETE, "displayResult");
    addControl(button);
  }

  public boolean getAllBooks(){
    List<Book> books = bookService.getAllBooks();
    renderJSON(books);
    return false;
  }
}

上記の例ではボタンをクリックするとprototype.jsのAjax.Requestによってページクラスの getAllBooks()メソッドが呼び出され、JSONが返却されます。 JSONが返却されるとHTML側ではJavaScriptのdisplayResult()関数が呼び出されます。

ファイルダウンロードの実装例

ファイルダウンロードを実現するページクラスの実装例を以下に示します。

public class FileDonwloadPage extends S2ClickPage {

  public FileDonwloadPage(){
    ActionLink link = new ActionLink("link", "ダウンロード", this, "onClick");
    addControl(link);
  }

  public boolean onClick(){
    String fileName = "sample.txt";
    InputStream in = getClass().getResourceAsStream("sample.txt");
    renderFile(fileName, in);
    return false;
  }
}

上記の例ではリンクをクリックするとページクラスのonClick()メソッドが呼び出され、 ファイルのダウンロードが行われます。

publicフィールドの活用

Seasar2ではJavaBeanに無用なアクセサを設けず、publicフィールドを活用することが推奨されています(もちろんカプセル化の観点からアクセサメソッドを用意したほうがよいケースもあります)。 しかし、ClickはJavaBean規約に従いアクセサメソッドを持ったJavaBeanの利用が想定されています。 そこで、S2ClickではClickでもpublicフィールドを活用するための機能を提供します。

Velocityテンプレート
Clickではビュー技術としてVelocityを使用します(JSPを利用することも可能です)。 Velocityは標準ではpublicフィールドの利用をサポートしていませんが、 S2Clickではプロパティアクセスの構文でpublicフィールドにもアクセスすることができます。
Tableコントロール
ClickのTableコントロールはJavaBeanのリストを表形式で表示することができますが、 ゲッターメソッドを持ったJavaBeanの利用しかサポートされていません。 Clickが標準で提供しているnet.sf.click.control.Columnの代わりに org.seasar.s2click.control.PublicFieldColumnを利用することでTableコントロールでpublicフィールドを使用することが可能になります。
フォームとオブジェクトの相互変換
S2Clickが提供するorg.seasar.s2click.control.S2ClickFormクラスのcopyTo()メソッド、およびcopyFrom()メソッドはpublicフィールドに対応しています。 また、S2ClickUtilsクラスのcopyFormToObject()メソッド、およびcopyObjectToForm()メソッドも同様にpublicフィールドに対応しています。

共通レイアウト

@Layoutアノテーションを使用することでページに共通テンプレートを適用することができます。 共通テンプレートのパスはs2click.diconのlayoutTemplatePathプロパティで設定します。

<component class="org.seasar.s2click.S2ClickConfig">
  <property name="mode">"debug"</property>
  <property name="layoutTemplatePath">"/layout.htm"</property>
</component>

ページクラスには以下のようにアノテーションを付与します。

@Layout
public class HelloPage extends S2ClickPage {
   ...

すると、ページクラスに対応するHTMLテンプレートではなく、 LayoutInterceptorのtemplateプロパティに設定された共通HTMLテンプレート(この場合は/layout.htm)が使用されます。 以下に共通テンプレートの実装例を示します。#parse($path)の部分にページクラスに対応する本来のテンプレートのレンダリング結果が出力されます。

<div class="header">ヘッダ</div>
#parse($path)
<div class="footer">フッタ</div>

なお、@Layoutアノテーションでテンプレートのパスを指定した場合はそちらが優先されます。

@Layout("/template.htm")
public class HelloPage extends S2ClickPage {
   ...