2003/04/04 更新
インフォサイエンス株式会社
稲村 大介 <inamura@infoscience.co.jp>
|
目次 |
- ・はじめに
- ・Strutsとは
- ・Strutsを使うメリット
- ・Struts の仕組み
- ・開発の実際
- struts-config.xml の編集
- JSP の編集
- アクションフォームビーンの作成
- アクションクラスの作成
- ・・タグライブラリ
- bean タグライブラリ
- html タグライブラリ
- logic タグライブラリ
- template タグライブラリ
- ・開発における注意点
- ・Struts 関連ツール
- ・情報源
|
|
現在、Webアプリケーション開発においてフレームワークは必須の存在となっている。
各社使用するフレームワークは様々だが、享受したいと考えるメリットは共通している。
まず、アプリケーションを開発するに当たり、そのアーキテクチャやクラス間の連携方法など検討する必要がある。
しかし、Webアプリケーションにおいてその仕組みはほぼ同じである為、アプリケーション毎に同じような仕組みを何度も設計・開発するのは避けたい。
フレームワークはこの問題を解決する。フレームワームは共通するアーキテクチャを抽象化し、再利用可能な形で提供される為、開発効率を向上させる事ができる。
フレームワークにはオープンソースで提供されているもの、有償で販売されているもの等数多く存在するが、中でも Jakarta Project の オープンソースフレームワークである Struts が最近注目されている。
Struts はシンプルだが非常に強力なフレームワークであり、導入事例も多く、情報が豊富である。
本稿では、主に Struts を使用した際のメリットや注意点について解説し、細部には踏み込まない。細部については 情報源 を参照して頂きたい。
|
|
Strutsとは、Jakarta Project によって開発されている、Java Servlet/JSP 技術を用いたWebアプリケーション開発を行う上で有用な、オープンソースフレームワークである。
100% Pure Java で記述されており、ほぼ全てのサーブレットコンテナでの動作が確認されている。私が過去に参加したプロジェクトでは Struts と組み合わせて、Tomcat、WebSphere、iPlanet
等のサーブレットコンテナを使用したが、いずれも問題なく動作した。
また、Struts をベースとしたフレームワークも幾つか開発されており、代表的なものとしては 日本IBM の「Extension for Struts」等がある。
Struts の2003年4月現在の最新バージョンは 1.0.2 である。本稿では、このバージョン 1.0.2 を対象に解説を行う。(1.1 は現在 RC1 で、リリース間近)
|
|
Struts を使うことにより得られるメリットは多いが、その中でも以下が重要である。
- ・開発効率が向上する
-
Webアプリケーション開発につきもののリクエストデータの取得や再表示時のデータの復元等は、Struts が行ってくれる。
Struts に慣れるまである程度(開発者によって異なるが 2 〜3週間)の時間は必要になるが、開発効率は確実に向上する。
- ・作業分担が容易になる
-
これは Struts のメリットというよりも MVC モデルのメリットだが、Model / View / Controller それぞれの結合が弱いため、作業の分担が容易となる。
ロジック(Model)を作る人、デザイン(View)を作る人、画面遷移(Controller)を作る人、等のような分担が可能である。
- ・画面デザインの変更に強い
-
これも MVC モデルのメリットだが、画面デザインの変更が発生した場合でも Model や Controller の修正は不要であり、View である JSP の修正だけで済む。
- ・一定の品質を保てる
-
Struts はフレームワークであり、動作の流れを規定している。開発者はその流れの上で必要なパーツを埋めていくという作業になる為、
開発者によって作り方が大きく違う、といった事態を防ぐ事ができる。
- ・国際化対応が容易
- Struts ではリソースバンドルを利用したマルチリンガルに対応している為、各国語用のリソースファイルを用意するだけでクライアントの環境に応じたコンテンツを表示することができる。
- ・柔軟な画面遷移が実現できる
- 画面遷移情報を全て設定ファイル(struts-config.xml)に持つ為、複雑になりがちな画面遷移処理を容易に記述する事ができる。
- ・JSP の可読性が向上する
- 標準で用意されているタグライブラリを利用する事によりJSPの記述に一貫性を持たせることができ、スクリプトレット等を埋め込む事による可読性の低下を防ぐ事が可能になる。
- ・教材として学習に利用できる
- 公開されているソースを読む事により、Servletの基本動作、MVC モデルを理解する事ができる。
|
|
|
Struts を用いた開発には、幾つか注意しなければならない事がある。開発を始める前に、以下について検討が必要になるだろう。
- ・自由度が高い
-
Struts は比較的自由度の高いフレームワークである。その為、ビジネスロジックを記述する箇所、フォームのエラーチェックを行う箇所等、
各プロジェクトで規約を設けるか、或いは Struts をベースとして、縛りをきつくしたフレームワークの構築が必要になる。
- ・データベースにアクセスする仕組みが無い
-
Struts にはデータベースを操作する為の仕組みが無い為、別途用意する必要がある。
Logstorage では独自にクラスを作成したが、Jakarta Project の OJB や Torque 等の使用も検討に値する。
- ・struts-config.xml
-
struts-config.xml にはシステム全ての画面遷移情報が記述される為、非常に大きなファイルとなり編集が困難となる。
これは Struts 1.0 では回避できない問題なので、アクション名の命名規則を決め、名称の重複が発生しないようにする必要がある。
Struts 1.1 では「Sub Application」が導入され、各サブシステム、機能等によって struts-config.xml を分割できるようになる。
|
|
Struts は MVC (Model-View-Controller)モデルを採用したフレームワークであり、以下のようになっている。
Struts MVC Model
 |
ActionServlet はクライアントからの要求を受け取ると、リクエストデータをアクションフォームビーンに格納し、アクションを呼び出す。
アクションは、アクションフォームビーンに格納されたデータを元にビジネスロジックを実行し、JSP を呼び出す。
アプリケーション毎に開発が必要となるのは、アクション、アクションフォームビーン、JSP と、ActionServlet が呼び出すアクション、
アクションフォームビーン、JSP を定義する struts-config.xml である。
作成する順番は、以下のようになると考えられる。
- ・struts-config.xmlの定義
- ・JSP の作成
- ・アクションフォームビーンの実装
- ・アクションクラスの実装
クラスの関連
 |
|
|
Webアプリケーション開発では、初期段階でプロトタイプ(HTML)を作成するのが良い。システムのイメージが掴みやすくなり、ユーザとの認識のズレを減らす事ができる。
また作成したプロトタイプはJSPへの変換元ソースとして使用できる為、実開発工程での工数削減にも繋がる。
尚、HTML から JSP への変換にはツールを使用することができる。Struts関連ツール を参照していただきたい。
では、以下のログイン画面プロトタイプを例に、開発手順を見ていこう。
register.html
<html>
<head>
<title>ユーザ登録画面</title>
</head>
<body>
<form>
ユーザID : <input type="text" name="userId"><br>
パスワード: <input type="password" name="password"><br>
<input type="submit" value="登録">
</form>
</body>
</html>
|
complete.html
<html>
<head>
<title>登録完了画面</title>
</head>
<body>
<h2>登録完了</h2>
ユーザID: infoscience<br>
パスワード: password<br>
</body>
</html>
|
struts-config.xml を編集する。
編集する内容は、
- ・どのアクションフォームビーンにリクエストデータを格納するのか
- ・どのアクションを呼び出すのか
- ・アクション実行後、どの JSP を呼び出すのか
という3点である。以下に定義例を示す。
struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
<form-beans type="org.apache.struts.action.ActionFormBean">
<form-bean name="registerForm"
type="jp.co.infoscience.sample.RegisterForm"/>
</form-beans>
<action-mappings type="org.apache.struts.action.ActionMapping">
<action path="/register"
name="registerForm"
scope="session"
type="jp.co.infoscience.sample.RegisterAction"
input="/register.jsp">
<forward name="success"
path="/complete.jsp"
redirect="false"/>
</action>
</action-mappings>
</struts-config>
|
赤字の部分が、アクションフォームビーンの定義になる。
アクションフォームビーン名、クラスを指定する。
青字の部分がアクションクラスの定義になる。
パス、アクションフォームビーン名、スコープ、クラス、遷移元JSP、遷移先JSPを指定する。
上記例では、/register という名前でリクエストがあった場合、
- ・jp.co.infoscience.sample.RegisterForm にリクエストデータを格納 (RegisterForm は session スコープ)
- ・jp.co.infoscience.sample.RegisterAction(execute method) を呼び出す
- ・jp.co.infoscience.sample.RegisterAction(execute method) 内で success が指定された場合、complete.jsp を表示
- ・jp.co.infoscience.sample.RegisterAction(execute method) 内で、自画面再表示が指定された場合、register.jsp を表示 (入力エラーの場合等)
という処理を行う事になる。
2) JSP の作成
プロトタイプを元に、以下のように JSP を作成する。
register.jsp
<%@ page language="java" contentType="text/html; charset=EUC-JP" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:html>
<head>
<title>ユーザ登録画面</title>
</head>
<body>
<html:errors/>
<html:form action="/register" method="post">
ユーザID : <html:text property="userId"/><br>
パスワード: <html:password property="password"/><br>
<html:submit value="登録"/>
</html:form>
</body>
</html:html>
|
complete.jsp
<%@ page language="java" contentType="text/html; charset=EUC-JP" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<html:html>
<head>
<title>登録完了画面</title>
</head>
<body>
<h2>登録完了</h2>
ユーザID: <bean:write name="user" property="name"/><br>
パスワード: <bean:write name="user" property="password"/><br>
</body>
</html:html>
|
赤字の部分が Struts タグライブラリの使用の宣言、青字の部分がStruts タグライブラリを使用している箇所である。
Struts で用意されているタグライブラリの概要は、タグライブラリ を参照して頂きたい。
以下のようにアクションフォームビーンを作成する。
RegisterForm.java
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
public class RegisterForm extends ActionForm {
private String userId = null;
private String password = null;
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public void reset() {
this.userId = null;
this.password = null;
}
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = null;
if (getUserId().length() < 1) {
errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("ユーザIDを入力してください。"));
}
return errors;
}
}
|
アクションフォームビーンは、org.apache.struts.action.ActionForm クラスを継承して作成する。
アクションフォームビーンで宣言される内容は、基本的に JSP ファイルのプロパティと一致させる必要がある。
入力値のチェックを行う validate メソッド、初期化を行う reset メソッドも用意する。
4) アクションクラスの作成
以下のようにアクションクラスを作成する。
RegisterAction.java
package jp.co.infoscience.sample;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
public class RegisterAction extends Action {
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession();
ActionErrors errors = new ActionErrors();
RegisterForm registerForm = (RegisterForm) form;
// データベースへの登録処理
// ....
session.setAttribute("user", registerForm);
return mapping.findForward("success");
}
}
|
アクションクラスは、org.apache.struts.action.Action クラスを継承して作成する。
次画面に渡したい値は基本的に request か session に追加する。
上記では、赤字の部分で、session に "user" という名前で RegisterForm のインスタンスを追加し、
青字の部分で、"success" のマッピング先にフォワードしている。
"success" のマッピング先は struts-config.xmlの編集 で complete.jsp にフォワードするよう定義されているので、complete.jsp が表示される。
以上が、Struts における大まかな開発の流れである。
元となるHTMLプロトタイプがあれば、アクションフォームビーンは機械的に作成でき、JSP についても基本的に大きな修正は必要ないので、
プログラマはロジックに注力する事ができる。
Struts 1.1 ではアクションフォームビーンを内部的に生成してくれる DynaBean という仕組みがあり、さらに容易となる。
|
|
|
Struts には、以下のタグライブラリが用意されている。
JavaBean の操作を行うタグライブラリ。
| タグ名 |
概要 |
| cookie |
指定したリクエストクッキーの値に基づいて変数を定義します。 |
| define |
指定した bean プロパティの値に基づいて変数を定義します。 |
| header |
指定したリクエストヘッダの値に基づいて変数を定義します。 |
| include |
動的なアプリケーションリクエストから応答をロードして bean として利用可能にします。 |
| message |
応答となる国際化されたメッセージ文字列を表現します。 |
| page |
指定したアイテムをbeanとしてページコンテキストから取り出します。 |
| parameter |
指定したリクエストパラメータの値に基づいて変数を定義します。 |
| resource |
Web アプリケーションのリソースをロードして bean として利用可能にします。 |
| size |
Collection または Map の要素数を含む bean を定義します。 |
| struts |
指定したStruts内部コンフィグレーション オブジェクトを bean として取り出します。 |
| write |
指定した bean プロパティの値を現在の JspWriter として表現します。 |
HTMLタグを生成するタグライブラリ。
| タグ名 |
概要 |
| base |
HTMLの <base> 要素を表現します。 |
| button |
ボタンフィールドを表現します。 |
| cancel |
キャンセルボタンを表現します。 |
| checkbox |
チェックボックスフィールドを表現します。 |
| errors |
蓄積されたエラーメッセージを条件付で表示します。 |
| file |
ファイル選択フィールドを表現します。 |
| form |
入力 フォームを定義します。 |
| hidden |
隠蔽フィールドを表現します。 |
| html |
HTMLの <html> 要素を表現します。 |
| image |
"image"形式の入力タグを画像ボタンを表現します。 |
| img |
HTMLのimg タグを表現します。 |
| link |
HTML の アンカ または ハイパーリンクを表現します。 |
| multibox |
チェックボックスフィールドを表現します。 |
| option |
セレクトオプションを表現します。 |
| options |
セレクトオプションのコレクションを表現します。 |
| password |
パスワードフィールドを表現します。 |
| radio |
ラジオボタンを表現します。 |
| reset |
リセットボタンを表現します。 |
| rewrite |
URIを表現します。 |
| select |
セレクト要素を表現します。 |
| submit |
サブミットボタンを表現します。 |
| text |
テキストフィールドを表現します。 |
| textarea |
Textarea要素を表現します。 |
JSP内で条件分岐、繰り返し等の制御を行うタグライブラリ。
| タグ名 |
概要 |
| equal |
要求された変数が指定した値と等しい場合、このタグ内の内容を評価します。 |
| forward |
ActionForward エントリによって指定したページへのフォワード制御。 |
| greaterEqual |
要求された変数が指定した値より大きいか等しい場合、このタグ内の内容を評価します。 |
| greaterThan |
要求された変数が指定した値より大きい場合、このタグ内の内容を評価します。 |
| iterate |
指定したコレクションで、このタグ内の内容を繰り返し評価します。 |
| lessEqual |
要求された変数が指定した値より小さいか等しい場合、このタグ内の内容を評価します。 |
| lessThan |
要求された変数が指定した値より小さい場合、このタグ内の内容を評価します。 |
| match |
指定した値が要求した変数の部分文字列に一致する場合、このタグ内の内容を評価します。 |
| notEqual |
要求された変数が指定した値と等しくない場合、このタグ内の内容を評価します。 |
| notMatch |
指定した値が要求した変数の部分文字列に一致しない場合、このタグ内の内容を評価します。 |
| notPresent |
指定した値がこのリクエストの中にない場合、このタグ内の内容を生成します。 |
| present |
指定した値がこのリクエストの中にある場合、このタグ内の内容を生成します。 |
| redirect |
HTTP Redirectを表現します。 | |