さて、ここまでで「個別詳細画面」を生成するためのデータの準備は完了です。次は、いよいよ今回のメイン画面となる「個別詳細画面」を設計してみましょう。個別詳細画面BookUpdate.jspのソースコードは、以下のとおりです。
BookUpdate.jsp
(「/chap04」フォルダに保存) |
<%@ page contentType="text/html;charset=Windows-31J" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<html:html>
<head>
<title>書籍情報更新・削除</title>
</head>
<body>
<h1 style="color:white;background-color:#525D76;">書籍情報更新・削除</h1>
<html:form action="/BookWriteAction">
<table border="0">
<tr>
<th align="right">ISBNコード:</th>
<td>
<logic:equal name="update.flag" value="true">
<html:text property="isbn" size="20" maxlength="20"
style="background:#EEeeEE" readonly="true" />
</logic:equal>
<logic:notEqual name="update.flag" value="true">
<html:text property="isbn" size="20" maxlength="20" />
</logic:notEqual>
</td>
</tr>
<tr>
<th align="right">タイトル:</th>
<td>
<html:text property="title" size="50" maxlength="50" />
</td>
</tr>
<tr>
<th align="right">著者名:</th>
<td>
<html:text property="author" size="15" maxlength="15" />
</td>
</tr>
<tr>
<th align="right">価格:</th>
<td>
<html:text property="price" size="5" maxlength="5" />円
</td>
</tr>
<tr>
<th align="right">出版社:</th>
<td>
<html:text property="publish" size="25" maxlength="25" />
</td>
</tr>
<tr>
<th align="right">配本日:</th>
<td>
<html:text property="published" size="12" maxlength="12" />
</td>
</tr>
<tr>
<td colspan="2">
<html:submit property="submit" value="保存" />
<html:reset property="reset" value="取消" />
</td>
</tr>
</table>
</html:form>
</body>
</html:html> |
HTMLタグライブラリについては、すでに第2回「Strutsアプリケーションの「枠組み」を学ぶ」でも紹介していますので、ここでは、新出となる<logic:equal>、<logic:notEqual>要素についてのみ簡単に紹介しておくことにします。
<logic:〜>で始まるLogicタグライブラリは、その名のとおり、条件分岐や繰り返し、データ比較など、ロジックの制御にかかわる機能を提供します。第3回「Strutsとデータベースの連携を学ぶ」でも登場した<logic:iterate>要素もまた、Logicタグライブラリに属するタグの1つで、与えられたJavaBeans配列をシーケンシャルに処理、出力処理するためのものでした。
ここで扱う<logic:equal>、<logic:notEqual>要素は、name属性で指定された(リクエスト)属性の内容がvalue属性の値に等しい(あるいは、等しくない)場合に、配下の要素を出力します。つまり、ここでは、リクエスト属性“update.flag”がtrueである場合は読み取り専用のテキストボックス(readonly="true")を、true以外の場合は通常の(入力可能な)テキストボックスを出力することを意味します。
リクエスト属性“update.flag”は、先ほどのアクションクラスBookUpdateViewProcessでセットされたもので、書籍情報一覧で[新規登録]が選択されたか、それとも既存のタイトルがクリックされたかを判別するフラグです。[新規登録]がクリックされた場合には、新規の書籍情報を登録するということでキー項目のISBNコードも含めて入力できるようにしておかなければなりませんが、既存タイトルがクリックされた場合には、既存データの更新となりますので、キー項目ISBN番号は入力できない状態にしておく必要があります(キーが変わっては適切なデータが更新できません)。
ちなみに、Logicタグライブラリには、<logic:equal>、<logic:notEqual>要素のほかにも、(リクエスト)属性やリクエストパラメータの値を判定し、処理の要否を判定するために、以下のような要素が用意されています。参考までに、主要なものを挙げておくことにしましょう。
Logicタグライブラリにおける条件分岐のための要素
|
.要素名 |
概要 |
|
logic:empty |
指定された変数が空の場合に配下のコンテンツを出力 |
logic:equal |
指定された変数がvalue属性の値と等しい場合に配下のコンテンツを出力 |
logic:greaterEqual |
指定された変数がvalue属性の値以上の場合に配下のコンテンツを出力 |
logic:greaterThan |
指定された変数がvalue属性の値より大きい場合に配下のコンテンツを出力 |
logic:lessEqual |
指定された変数がvalue属性の値以下の場合に配下のコンテンツを出力 |
logic:lessThan |
指定された変数がvalue属性の値より小さい場合に配下のコンテンツを出力 |
logic:match |
指定された変数がvalue属性の値を含む場合に配下のコンテンツを出力 |
logic:notEmpty |
指定された変数が空でない場合に配下のコンテンツを出力 |
logic:notEqual |
指定された変数値がvalue属性の値に等しくない場合に配下のコンテンツを出力 |
logic:notMatch |
指定された変数がvalue属性の値を含まない場合に配下のコンテンツを出力 |
logic:notPresent |
指定された変数が存在しない場合に配下のコンテンツを出力 |
logic:present |
指定された変数が存在する場合に配下のコンテンツを出力 |
|
参考
Logicタグライブラリで提供されているカスタムタグの多くは、JSTL(JSP Standard TagLibrary)で置き換えることが可能です。本連載ではコードの一貫性を優先して、一律、Logicタグライブラリを利用することにしますが、今後はできるだけJSTLを利用していくことをお勧めします。なお、JSTLについては、連載「基礎から学ぶサーブレット/JSP」で後日紹介する予定です。
「.jsp」ファイルでビューレイアウトはできました。しかし、このままではせっかくアクションクラスBookUpdateViewProcessで用意した更新用のデータが反映されません。フォームに対して、用意されたデータを初期値として渡すには、どのようにしたら良いのでしょうか。
いくつか方法はありますが、ここでは、アクションフォームBeansのresetメソッドを利用する方法について紹介します。現在のフォームに関連付けられたアクションフォームBeans(ここでは、<html:form>要素のaction属性“BookWriteAction”に関連付けられたアクションフォームBeans。後述のstruts-config.xmlを参照してください)は、[保存]ボタンがクリックされたときだけ呼び出されるわけではありません。
アクションフォームBeansは、「.jsp」ファイルを最初に表示するときにも呼び出され、フォーム上の各種入力要素を初期化するために使用されているのです。その初期化の役割を担うのが、ActionForm#resetメソッドの役割です。
BookUpdateForm.java |
package struts;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class BookUpdateForm extends ActionForm {
private String isbn;
private String title;
private String author;
private String price;
private String publish;
private String published;
public String getIsbn() {return isbn;}
public String getTitle() {return title;}
public String getAuthor() {return author;}
public String getPrice() {return price;}
public String getPublish() {return publish;}
public String getPublished(){return published;}
public void setIsbn(String isbn) {this.isbn=isbn;}
public void setTitle(String title) {this.title=title;}
public void setAuthor(String author) {this.author=author;}
public void setPrice(String price) {this.price=price;}
public void setPublish(String publish) {this.publish=publish;}
public void setPublished(String published){this.published=published;}
public void reset(ActionMapping map, HttpServletRequest request){
try {
// リクエストパラメータの文字エンコーディングを指定
request.setCharacterEncoding("Windows-31J");
/* リクエスト属性“update.flag ”の有無によって処理を分岐します。
* “update.flag ”が存在する場合(つまり、更新用のページとして
* JSPページが呼ばれた場合)、リクエスト属性“book.update.info ”
* に保存されたBookInfoオブジェクトの各プロパティ値を、アクショ
* ンフォームBeans内で指定したプロパティにセットします */
if(request.getAttribute("update.flag")!=null){
BookInfo objBok=
(BookInfo)(request.getAttribute("book.update.info"));
isbn =objBok.getIsbn();
title =objBok.getTitle();
author =objBok.getAuthor();
price =objBok.getPrice();
publish =objBok.getPublish();
published=objBok.getPublished();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} |
初期値をセットする方法は、極めて簡単です。ただ、アクションフォームBeansの該当するプライベート変数に対して、初期値としてセットしたい値をセットするだけです。これは、対象がテキストボックスだけでなく、ラジオボタンやコンボボックスなど、そのほかの入力要素の場合でも同じです。
なお、ここでは初期値の設定のほかに、もう1つ行っていることがあります。それは、リクエストデータの文字エンコーディング設定です。Strutsでは、このように文字エンコーディングを明示的に宣言しておかないと、リクエストデータに日本語(2バイト文字)が含まれる場合に文字化けの原因となりますので、注意してください。
今回は、取りあえず何も動作しないダミーのアクションクラスを用意しておくことにします。Strutsは、BookUpdate.jspの表示時に、関連するアクションクラスまでチェックしているので、取りあえず、正常に「.jsp」ファイルが表示されるかどうかを確認するためには、このように空のアクションクラスを用意しておく必要があります。
したがって、現時点ではBookUpdate.jspの[保存]ボタンをクリックしても一覧表に戻るだけで、何のアクションも行われません。更新ロジックに関する詳細は、次回改めて紹介することにしましょう。
BookUpdateProcess.java |
package struts;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.*;
import org.apache.struts.action.*;
public final class BookUpdateProcess extends Action {
public ActionForward execute (ActionMapping map,
ActionForm fm,
HttpServletRequest request,
HttpServletResponse response) {
// 無条件に成功のフラグのみを戻り値として返します
return map.findForward("success");
}
} |
最後に、これまで作成したアクションクラス、アクションフォームBeans、「.jsp」ファイルを、コンフィグレーションファイル上でマッピング(関連付け)して、完了です。struts-config.xmlに、以下リストの赤字部分を追記してください。
struts-config.xml |
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
…中略…
<form-beans>
<form-bean name="BeginForm" type="struts.BeginForm" />
<form-bean name="BookUpdateViewForm"
type="org.apache.struts.action.DynaActionForm">
<form-property name="isbn" type="java.lang.String" />
</form-bean>
<form-bean name="BookUpdateForm" type="struts.BookUpdateForm" />
</form-beans>
…中略…
<action-mappings>
…中略…
<action path="/BookWriteViewAction"
type="struts.BookUpdateViewProcess"
name="BookUpdateViewForm" scope="request">
<forward name="success" path="/chap04/BookUpdate.jsp" />
</action>
<action path="/BookWriteAction" type="struts.BookUpdateProcess"
name="BookUpdateForm" scope="request">
<forward name="success" path="/BookViewAction.do" />
</action>
</action-mappings>
</struts-config> |
<action>要素の設定については、すでに第2回でも紹介したところなので、特筆すべき点はありません。復習も兼ねて、第2回の解説と照らし合わせながら、自分なりに解釈してみてください。
すべての準備が完了したら、第3回で作成した「書籍情報一覧」画面から各タイトル、もしくは[新規登録]リンクをクリックしてください。前者では該当書籍に関する更新画面が、後者ではブランクの登録用画面が、それぞれ表示されれば成功です(完成図は冒頭の図を参照)。
以上、今回はActionForm、DynaActionFormを利用したデータ授受の方法について学習しました。アクションフォームBeansが単なるリクエストパラメータの格納先というだけでなく、リクエストデータを一元的に操作・管理する「コントロールタワー」であることが実感できたのではないでしょうか。
Strutsでは、このように「データ」管理のコアであるアクションフォームBeansと「ロジック」管理のコアであるアクションクラスとを、明確に役割分担を定義しているわけです。
次回は、今回生成した登録・更新画面からデータを登録するサンプルを通じて、ユーザーデータを「検証」するValidator機能について学ぶことにします。どうぞお楽しみに。