ryhmrt’s blog

フィリピンから日本に戻った意識低い系プログラマの雑記

Struts2あれこれ

仕事でStruts2を触ったので、そのメモ。

ActionFormみたいな何か

ModelDrivenインターフェースを実装することで、対象のモデルクラスのフィールドをアクションにMixinするような感じにできる。

getModel() メソッドでは、編集対象のモデルオブジェクトを返す。

通常は以下のような感じになるかと思う。

public class HogeAction extends ActionSupport implements ModelDriven<Hoge> {

    private Hoge hoge = new Hoge();

    public String execute() {
        return SUCCESS;
    }

    public Hoge getModel() {
        return hoge;
    }

}

リクエストパラメータで渡ってきた値は自動的にモデルオブジェクトに設定される。

モデルに設定されたプロパティはStrutsのタグなどで参照可能。

<s:textfield key="hogehoge" />

既存のデータをモデルオブジェクトに読み込む

編集処理などでは、DBからモデルの内容を読み込みたいと思うだろうが、通常のアクション処理の中でモデルを書き換えてもうまくいかない。

Struts2がgetModel()する前にモデルを初期化しなければいけないのだ。

アプローチはたぶん2つくらいある。

  1. getModel() 内でデータを読み込む
  2. Preparableインターフェースを実装して、prepare()内でデータを読み込む

まず、どちらにせよ、リクエストパラメータはServletRequestのものを生で使う必要がある。

implements ServletRequestAware ってやると幸せ。

Preparableの例は以下のような感じ。

public class HogeAction extends ActionSupport implements ModelDriven<Hoge>, ServletRequestAware, Preparable {

    private Hoge hoge = new Hoge();
    private HttpServletRequest request;

    public String execute() {
        return SUCCESS;
    }

    public Hoge getModel() {
        return hoge;
    }

    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }

    public void prepare() {
        int id = Integer.parseInt(request.getParameter("hoge_id"));
        hoge = モデルオブジェクト読込処理(id);
    }

}

CSSのclass属性を設定する

cssClass属性を設定すればOK.

<s:textfield key="hoge" cssClass="bar" />

org.apache.struts2.util.TextProviderHelperのWARNログがうるさい

log4j.xmlに以下の設定。

<category name="org.apache.struts2.util.TextProviderHelper">
  <priority value="error"/>
</category>

Actionで発生した例外をログ出力しつつエラーページを表示

struts.xml抜粋

<interceptors>
  <interceptor-stack name="myDefaultStack">
    <interceptor-ref name="defaultStack">
      <param name="exception.logEnabled">true</param>
      <param name="exception.logLevel">ERROR</param>
    </interceptor-ref>
  </interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"/>
<global-results>
  <result name="systemError">/error.jsp</result>
</global-results>
<global-exception-mappings>
  <exception-mapping result="systemError" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>