S2Strutsのお奨めパターン

S2Strutsを使うときは1.2系/1.3系のバージョンにかかわらず共通で次のパターンでいくのがわかりやすくて安全だと思います。

  • 基本的にjspとActionFormとActionとInitActionは1対1対1対1で作成
  • jspからのサブミットはformのaction属性に対応するActionへのみとする(1つのフォームを異なるActionへサブミットするs2struts:submitタグを記述しない)
  • 呼び出されたActionでは次画面の表示に必要な処理は行わない
  • 次画面の表示に必要な情報はその画面(jsp)のs2struts:initタグから呼び出すInitActionで行う

たとえば、従業員のマスタメンテで編集画面(edit.jsp)から確認画面(confirm.jsp)へ遷移するとします。

edit.jsp
  <html:form action="/edit">
    ・・・
    <s2struts:submit action="@{editAction.goConfirm}">確認</s2struts:submit>
    <s2struts:submit action="@{editAction.goPrevious}" cancel="true">戻る</s2struts:submit>
  </html:form>

編集画面(edit.jsp)では、前画面に戻りたくても次画面に進みたくてもひとつのformからはs2struts:submitタグを使って同じActionにサブミットするようにするのがいいです。ひとつのForm内の複数のs2struts:submitタグで異なるActionを呼び出すと、呼び出したActionに対応するバリデーション処理がスキップされてしまうことがあるからです(S2Struts1.2では必ずスキップされる、1.3では回避できる)。

編集画面(edit.jsp)で「確認」ボタンが押されたとします。呼び出されるActionでは次画面の表示に必要な処理は行ないません。ここではただForwardするだけにします(ただし、ActionFromに対するバリデーションは行うにようにしています)。

EditAction
public class EditAction {

    @StrutsActionForward(path = "/WEB-INF/view/confirm.jsp")
    public static final String CONFIRM = "confirm";

    @StrutsActionForward(path = "/WEB-INF/view/list.jsp")
    public static final String LIST = "list";

    public String goConfirm() {
        return CONFIRM;
    }

    public String goPrevious() {
         return LIST;
    }
}

Forwardされた先のjspでは s2struts:init タグにより画面表示に必要な情報を取得するInitActionを呼び出します。

confirm.jsp
  <html:form action="/confirm">
    <s2struts:init action="@{confirmInitAction.init}"/>
    ...
    <html:hidden property="empName" />
  ...
    <s2struts:submit action="@{confirmAction.goStore}" >更新</s2struts:submit>
    <s2struts:submit action="@{confirmAction.goPrevious}">戻る</s2struts:submit>
  </html:form>

s2struts:init タグは、html:form タグの内側に記述します。こうすることでこのjspに対応するActionFromをInitActionで扱えるようになります。html:form タグでこのjspに関連づいたActionFormのインスタンスがrequestスコープに入れられ、それが自動でInitActionにバインディングされるからです。

そのため、s2struts:init タグから呼び出されるConfirmInitActionでは、前画面のActionFrom(editForm)とこれから表示する画面のActionFrom(confirmForm)の両方が扱えます。

ConfirmInitAction
public class ConfirmInitAction {

    private ConfirmForm confirmForm;

    private EditForm editForm;

    public void setEditForm(EditForm editForm) {
        this.editForm = editForm;
    }

    public void setConfirmForm(ConfirmForm confirmForm) {
        this.confirmForm = confirmForm;
    }
    
    public void init() {
        // ホントはBeanUtilsとかでコピー
        confirmForm.setEmpNo(editForm.getEmpNo());
        confirmForm.setEmpName(editForm.getEmpName());
        ...
    }
}

ここでは前画面のeditFormの値をこれから表示するconfirmFormにつめているだけですが、必要であればDBから取得したデータを設定することもできます。
confirmFormに値が設定されると、confirm.jsp内でその値にアクセスすることができます。たとえば、confirm.jsp としていますが、ConfirmInitActionのinitメソッドで設定された値が出力されます。


ちょっと簡略化して記述しているのでこのままで動かないかもしれませんが、だいたいこのパターンでいけるんじゃないかなぁと思います。

ちなみに、一般的な

#{confirmAction.goStore}

ではなく

@{confirmAction.goStore}

と書いていますが、これはJSP2.1の仕様とバッティングしないようにしているためです。「#」と書くとWTPの検証で警告がでるのでかわりに「@」にしています。S2Struts的にはどの文字で始まっているか見ていないので何でもいいんですよね。