もっと便利に Struts
概要
これまでは主に Struts の基本機能について説明をしてきました。 今回は、Struts アプリケーションを開発するにあたって、便利な機能を提供してくれるコンポーネントについて紹介します。
今回、紹介するコンポーネントはJakarta Commons の Validator と FileUpload です。
もちろん、Commons コンポーネントにはここで紹介する以外にも便利なコンポーネント(DbUtils や Email など)がありますが、
ここでは紹介を省略します。
個人的には Commons 以外にも Struts アプリケーション開発を支援してくれる技術として、
HibernateやSpring、
Velocity(これは使ってみたい)などを利用していたりもしますが、
それらはまた次の機会にということで…。
サンプルアプリケーション
今回は第3回で作成した リソースファイルを利用したログインアプリケーション(日本語対応版) を利用して説明します。
Validator を利用した入力値の検証
そもそも入力値の検証って??
これまでチュートリアルでは、議論を簡単化するために入力値チェックについては触れてきませんでした。
しかし、フォーム項目の入力値チェックは、ユーザ入力が String (HTTP Request) でしかない
Web アプリケーションの信頼性を向上させるためには、必須の機能です。
フォーム項目の入力値チェックを行う事で、Web アプリケーションに入力されるデータに(型のような)制約を与えることができます。
以降、ユーザのフォーム入力をチェックする方法について説明します。
Struts の検証機構(Validator を利用しない方法)
今回のメインは Validator を利用したフォーム入力値のチェックですが、
Struts 自体にもフォーム入力をチェックする機構は存在します。
Struts でフォーム入力を扱うには、ActionForm クラスを継承したフォームオブジェクトを作成しました。
「フォームオブジェクトには、setter と getter を用意しフォーム入力値をセットする」というのが
第1回で学んだことでした。
しかし、フォームオブジェクトには setter, getter による値の操作以外にも、
入力値の検証 (validate)、初期化 (reset)といった仕組みが用意されています。
ActionForm の入力値検証機構を利用するには、フォームクラスに validate メソッドを実装します。
実際の例で説明します。
第3回で作成したログインアプリケーションは、名前フィールドやパスワードフィールドに文字列が入っていなくても、
「不正な入力」としては扱われません。
そこで、今回は"名前フィールドに文字列が入力されなかった場合"を不正な入力として扱い、不正な入力が与えられた場合、
ログインページに遷移を戻すという機構を追加します。
この機構を追加するためには、以下の作業を行います。
- エラーメッセージをリソースファイルに記述
- 入力値が不正だった場合の遷移先を struts-config.xml に記述する。
- フォームクラスに入力値を検証するためのメソッドを作成する。
- エラーメッセージを表示するための、タグを JSP に埋め込む
エラーメッセージをリソースファイルに記述
入力値を検査するためには、入力値が不正な値であった場合に利用するエラーメッセージを用意しなければいけません。
この理由は後で明らかになりますが、Struts フレームワークにおいては入力値不正の是非は、
エラーメッセージの有無で判断されるためです。
また、このエラーメッセージを読込むリソースファイルはキー org.apache.struts.action.MESSAGE で指定されたファイル
(デフォルトのメッセージリソース)でなければなりません。
そこで、resources 以下に errors.properties というファイルを作り、struts-config.xml の
<message-resources> タグで、キーを指定せずにリソースファイルとして登録しましょう。
(errors.properties の中身) error.username.invalid=ユーザ名が不正です。
(struts-config.xml) <message-resources parameter="resources.errors" />
struts-config.xml の修正
次に、「入力値チェックを行う遷移であるかどうかのフラグ」と「不正な入力が与えられた場合の遷移先」を
struts-config.xml に定義します。
どちらも <action> タグの属性によって指定します。
「入力値チェックを行う遷移であるかどうかのフラグ」は validate 属性によって、
「不正な入力が与えられた場合の遷移先」は input 属性によって定義します。
(”遷移先”なのに属性が input なのは奇妙ですが、これも struts の仕様です。)
struts-config.xml 中、ログインアクション定義を以下のように修正してください。
<action path="/Login" name="InputForm" type="login.LoginAction" validate="true" input="/pages/login.jsp"> <forward path="/pages/error.jsp" name="error" /> <forward path="/pages/success.jsp" name="success" /> </action>
入力値を検証するメソッドの作成
さて、いよいよ入力値を検証するメソッドの作成です。
入力値を検証するメソッドは、スーパークラスである ActionForm の validate メソッド(以下)をオーバーライドして作成します。
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request)
では、実際に validate メソッドを追加します。
以下のメソッドを InputForm に追加してください。
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (username.length() == 0) {
errors.add("username_invalid", new ActionMessage("error.username.invalid"));
}
return errors;
}
上記のメソッドでは、もし username の長さが 0 であれば、
org.apache.struts.action.MESSAGE で指定されたリソースファイルのキー "error.username.invalid" から、
ActionMessage を生成し、ActionErrors オブジェクトに登録します。
Struts のコントローラは validate の結果(errors)を受け取り、もし ActionErrors オブジェクトが空でなければ、
予め決められたリクエストに ActionErrors を登録し、input 属性で指定された遷移を行います。
この時、Action の実行は行われません。
エラーメッセージを表示するための、タグを JSP に埋め込む
最後に、エラーメッセージを表示するためのタグを JSP に埋め込みます。
<html:errors /> タグを JSP に記述してください。
<html:errors /> <html:form action="/Login">
このタグは、もし空でない ActionErrors オブジェクトが存在する場合にはエラーメッセージを表示するタグです。
エラーメッセージが表示されない
以下の理由が考えられます。
- 指定するキーの値が間違っている
- struts-config.xml で action に validate="true" を記述していない
- <html:errors /> を書き忘れている
ここまでのファイルをこちらに置いておきます。
Validator の利用
では、いよいよ Validator を利用して
フォームの入力値チェックを行います。
Validator コンポーネントは 0 値チェックや int 型チェックなど、基本的な validate 機能を提供してくれるコンポーネントです。
特に、Struts アプリケーションにおける Validator コンポーネントは、
クライアントサイド(JavaScript)とサーバサイド(validate メソッド)の双方の validate 機能を提供します。
Validator はフォームの各データ項目に対する制約を XML で記述することで設定します。
では、実際に先程の機能を Validator を利用して実現してみましょう。
Validator を利用するには、以下を行わなければなりません。
- フォーム項目に対する validation ルールの記述
- エラーメッセージ用のリソースファイルの準備
- Validator によるサーバサイド検証のため、フォームオブジェクトの修正
- struts-config.xml の編集
validation ルールの記述
Validator における validation ルールは XML ファイルによって記述します。
実は Struts-blank から作成した Web アプリケーションには、既に Validator コンポーネントを利用するための準備が整っています。
(WEB-INF/lib 以下に commons-validator.jar があるのも、その証拠)。
Struts-blank から作成した Web アプリケーションで、Validator の制約を記述するには WEB-INF/validation.xml を編集します。
validation ルールはフォーム毎に記述します。
validation.xml の form-set の子要素 form に制約を与えるフォームの論理名(struts-config.xml における form-bean の name)を記述し、
form の子要素 field の property 属性で実際に制約を与えるフォーム項目を指定し、depends 属性で与える制約を記述します。
例えば、サンプルアプリケーションに対する制約は以下のようになります。
<formset> <form name="InputForm"> <field property="username" depends="required"> <arg0 key="inputform.username" /> </field> </form> </formset>
リソースファイルの準備
次にエラーメッセージを表示するためのリソースファイルを用意します。
Validator はリソースファイル中、"errors.(バリデータ名)" で指定されたキーを持つメッセージを利用します。
そこで、上記の required バリデータのためのエラーメッセージをリソースファイルに記述します。
(errors.properties)
errors.required={0} は必須項目です。
リソースファイル中、{0}は置換文字列であり、この文字がどの文字列によって置換されるかは field の子要素、
<arg0 >タグによって指定されています。
上記の例では、リソースファイル中、キー "inputform.username" で指定される値が置換対象となります。
そこで、error.properties に inputform.username も追記します。
(errors.properties) inputform.username=ユーザ名
フォームオブジェクトの修正
次に、Validator の検証機構を利用するため、フォームオブジェクトに修正を加えます。
具体的には、ActionForm を継承するのではなく、 org.apache.struts.validator.ValidatorForm を継承するようにします。
public class InputForm extends ValidatorForm {
また、validate メソッドに相当する機能は Validator が行ってくれるので、validate メソッドを削除します。
struts-config.xml の編集
最後に、Validator をプラグインとして読込むため、struts-congig.xml を編集します。
struts-config.xml の最後に以下を加えてください。
<plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in>
ここまでの修正を終えたら、Web アプリケーションを再起動し validate 機能が働いているかどうかを確認してください。
クライアントサイドの検証(JavaScript)
最初に述べたように、Validator を利用することで JavaScript による検証も可能となります。
JavaScript による検証を行うには JSP ファイルの任意の場所に
<html:javascript formName="InputForm (struts-config.xml で指定したフォーム名)"/> タグを
<html:form > の onsubmit 属性に onsubmit="return validateInputForm(this)" を記述してください。
(InputForm は <html:javascript > で指定したフォームの名前)
主なバリデータ
required 以外にも、Validator には種々のバリデータが存在します。
主なバリデータの簡単な一覧を以下に示しておきます(Struts In Action 参考)。
より詳しい情報は他を参照してください。
| バリデータ | 内容 |
|---|---|
| required | 必須項目のチェック |
| mask | 正規表現で指定したマスクのチェック |
| range | 値域のチェック |
| maxLength | 最大値チェック(長さ) |
| minLength | 最小値チェック(長さ) |
| byte | 変換可能性のチェック |
| short | 変換可能性のチェック |
| integer | 変換可能性のチェック |
| long | 変換可能性のチェック |
| float | 変換可能性のチェック |
| double | 変換可能性のチェック |
| date | 日付チェック |
| creditCard | カード番号のチェック |
| メールアドレスのチェック |
ここまでのファイルをこちらに置いておきます。
FileUpload を利用したファイルのアップロード
最後に、FileUploadを利用したファイルのアップロードについて
説明します。
今回は、先程のログインページにてファイルをアップロードし、そのファイルを保存するというアプリケーションを作成します。
JSP の修正
ファイルのアップロードを行うために、フォームの属性に enctype="multipart/form-data" を指定し、 <html:file> タグを用意して、ファイルを指定します。
(login.jsp) <html:form action="/Login" onsubmit="return validateInputForm(this)" enctype="multipart/form-data"> ... <tr> <td align="right">ファイル: </td> <td><html:file property="file" /></td> </tr>
フォームオブジェクトへのプロパティの追加
ファイルを扱うためのプロパティをフォームオブジェクトへ追加します。
Struts では org.apache.struts.upload.FormFile クラスのオブジェクトでアップロードされるファイルを操作します。
そこで、org.apache.struts.upload.FormFile のプロパティと、その setter, getter を用意します。
(InputForm.java)
public FormFile getFile() { return file; }
public void setFile(FormFile file) { this.file = file; }
Action クラスの修正
最後に Action クラスにファイルを保存する処理を記述します。
処理としては、普通に Java のプログラムでファイルにデータを書き込む時と同じ流れです。
(LoginAction.java)
...
// ファイルオブジェクトの取得
FormFile file = inputForm.getFile();
// ファイル名の取得
String fileName = file.getFileName();
// ファイルサイズの取得
int fileSize = file.getFileSize();
if (fileSize > 0) {
// コンテキストパスと同じディレクトリに、OutputStream を開く(書き込み用)
OutputStream os = new FileOutputStream(
servlet.getServletContext().getRealPath("") + File.pathSeparator + fileName);
// ファイル読込み用の InputStream を開く
InputStream is = file.getInputStream();
int readBytes = 0;
byte[] buffer = new byte[1024];
// ファイル書き込み
while ((readBytes = is.read(buffer, 0, 1024)) != -1) {
os.write(buffer, 0, readBytes);
}
os.close();
}
...
おわりに
今回は、Validator と FileUpload の使い方を勉強しました。 FileUpload に関しては、特に何か変わったことがあったというわけではありませんが、 必要になる機能であることが予測されるので、あえて紹介しました。
ここまでのチュートリアルで Struts が完全にわかったということにはならないと思いますが、 少なくとも基礎的な部分は理解ができているはずです。 Struts には、ここで紹介した以外にも DynaActionForm など様々な技術がありますが、 基礎が理解できていれば、それほど理解に苦しむ仕組みではないと思います。
by Nobuyuki KANEKO


