2007 年 4 月 17 日 23 時 46 分

キャンセルと検証を組み合わせる


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


[写真]


キャンセルに対応したので、ついでに検証を実装し、
キャンセルが検証コードを回避することを確認してみよう。
ま、自分の復習のためってことで。

検証を行うためには、以下のような修正が必要となる。

1. ActionrForm#validate の実装
2. Struts 設定ファイルの <action> へ input 属性を追加
3. 検証エラーを表示する JSP に、専用のタグを追加

まず、FilterInfoForm#validate を実装する。

========== FilterInfoForm#validate ==========
    @Override
    public ActionErrors validate(ActionMapping mapping,
            HttpServletRequest request) {

        ActionErrors errors = new ActionErrors();

        String defaultAction = info.getDefaultAction();
        String node = info.getNote();

        if (node == null || node.length() == 0) {
            ActionMessage m =
                    new ActionMessage("備考を入力してください。",
                            false);
            errors.add("info.note", m);
        }

        if (defaultAction == null
                || defaultAction.length() == 0) {
            ActionMessage m =
                    new ActionMessage(
                            "既定の処理を選択してください。", false);
            errors.add("info.defaultAction", m);
        } else if (!defaultAction.equals("allow")
                && !defaultAction.equals("deny")) {
            ActionMessage m =
                    new ActionMessage("既定の処理の値が不正です。",
                            false);
            errors.add("info.defaultAction", m);
        }

        if (!errors.isEmpty()) return errors;

        return super.validate(mapping, request);
    }
========== end of FilterInfoForm#validate ==========

ぱぱっと簡単に、備考欄が空白ならエラーとしてみた。
既定の処理についても厳密にチェックしている。

入力画面にはラジオボタンを使っているため、
普通に入力するだけでは無効な値になることはないが、
フォームの送信は簡単に偽装できるため、
しっかりと確認しておく必要がある。

次に、Struts 設定ファイルの <action> を修正する。

        <!-- 情報編集画面 -->

        <action path="/filter/edit-info"
                name="filterInfoForm" scope="request"
                validate="false"
                type="jp.loafer.test.actions.EditFilterInfoAction">

            <!-- 情報編集画面用の View へ -->
            <forward name="success"
                    path="/WEB-INF/pages/filter/edit-info.jsp" />

        </action>

        <!-- 情報更新 -->

        <action path="/filter/update-info"
                name="filterInfoForm" scope="request"
                input="/WEB-INF/pages/filter/edit-info.jsp"
                type="jp.loafer.test.actions.UpdateFilterInfoAction"
                cancellable="true">

            <!-- 成功時は一覧画面へ戻る -->
            <forward name="success" path="/filter/list.do" />

            <!-- キャンセル時も一覧画面へ戻る -->
            <forward name="cancel" path="/filter/list.do" />

            <!-- 検証エラー時は、input 属性のパスへ戻る -->

        </action>

FilterInfoForm を使っている <action> を修正する。
今回の修正は 2 箇所ある。

/filter/edit-info での filterInfoForm の役割は、
ユーザが入力するフィルタ情報を格納するための
Form Bean のインスタンスを「準備する」だけだ。

この時点ではユーザの入力を扱う訳ではなく、
このフォームの内容を検証する必要はないので、
忘れずに validate 属性に false を指定しておく。

/filter/update-info では、フォームを検証する必要がある。
既定値が true である validate 属性の指定は不要だが、
検証エラーが発生する可能性のある <action> には、
必ず input 属性でエラー時の転送先を指定しておく。

最後に、JSP を、エラー表示用の修正する。

========== /WEB-INF/pages/filter/edit-info.jsp ==========
<?xml version="1.0" encoding="UTF-8" ?>

<%@ page contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>

<%@ taglib prefix="html"
        uri="http://struts.apache.org/tags-html" %>

<%@ taglib prefix="bean"
        uri="http://struts.apache.org/tags-bean" %>

<!DOCTYPE html PUBLIC
        "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html:html xhtml="true">

<head>
    <meta http-equiv="Content-type"
            content="text/html; charset=UTF-8" />
    <title>パケットフィルタ: 編集</title>
</head>

<body>
    <h1>パケットフィルタ: 編集</h1>
    <html:form action="/filter/update-info">
        <p>
            既定の処理:
            <html:radio property="info.defaultAction"
                    errorStyle="background-color: #fcc"
                    value="allow" />許可
            <html:radio property="info.defaultAction"
                    errorStyle="background-color: #fcc"
                    value="deny" />拒否
            <html:messages id="msg" property="info.defaultAction">
                <font color="red">
                    <bean:write name="msg" />
                </font>
            </html:messages>
        </p>
        <p>
            備考:
            <html:text property="info.note" size="60"
                    errorStyle="background-color: #fcc" />
            <html:messages id="msg" property="info.note">
                <font color="red">
                    <bean:write name="msg" />
                </font>
            </html:messages>
        </p>
        <p>
            <html:submit>更新</html:submit>
            <html:cancel>キャンセル</html:cancel>
        </p>
    </html:form>
</body>

</html:html>
========== end of /WEB-INF/pages/filter/edit-info.jsp ==========

<bean:write> を使うので、tags-bean の参照を追加する。

入力項目に、errorStyle 属性を追加し、
エラー時には赤い背景になるようにした。
(ラジオボタンの背景が変わるかどうかはブラウザ依存だが)

今回は、エラーメッセージを各項目の近くで表示する。
<html:messages> を項目毎に使用し、
property 属性を指定することで、
対応する項目の入力エラーのみが表示されるようにする。

では、実験してみよう。

ブラウザを起動し、いきなり以下の URL を開く。
これは、不正な値でフォームを送信するテストだ。

http://localhost:8080/struts-test/filter/update-info.do?info.defaultAction=hoge

正しく検証が行われていれば、
既定の処理も備考も両方ともエラーとなるはずである。
入力値が不正なままでは、何度更新ボタンを押しても、
正常にエラー画面が表示される。

でも、キャンセルを押した場合は、
たとえ入力値が不正なままでであっても、
ちゃんと一覧画面に戻るのである。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.