第6回 JSPでプレゼンテーション層をどう作る?



樫山友一
2002/6/27


 今回は、プレゼンテーション層の設計を解説します。採用するアーキテクチャはJSP(JavaServer Pages)です。JSPは簡単に動的なページを作り出せるのでとても便利ですが、しっかりとしたフレームワークを用いて開発をしないとコードのメンテナンスが悪くなり、後で苦労することになります。そうならないためのテクニックを含めて、今回の解説をします。

 メンテナンス性のよいサイトをJSPを用いて構築する場合、以下のような点に気を付ける必要があります。
  1. ページ遷移と実際のJSPファイルが密に結び付いてしまうのを避ける

  2. 入力データなどのチェックロジックをJSPに直接実装しないようにする

  3. JSPのコードにはJavaのコードをそのまま実装せず、ロジックは外部のクラスとして実装する

 これらをうまく解決するために、J2EEのフレームワーク製品やJavaBeansを用いてJSPのページを開発します。第4回「実装のアーキテクチャを決めよう」の解説で、strutsを用いた開発を例にしました。J2EEフレームワーク製品の概略については、第4回を参照してください。strutsもほぼ同等の機能を持っています。これにより、上記の1と2をうまく解決してくれます。では、strutsを用いることを前提に設計を進めていきましょう。

 念のためシステムの概要を再度以下に示します。

【受注システムの概要】
 オペレータは、FAXか電話にて顧客から注文を受ける。注文を受けたときに顧客データをチェックし、登録されていなければ顧客の登録を行う。その後、注文を受けて請求書のデータを作成し、請求書をプリントアウトして顧客に発送する。オペレータは、顧客からの注文の問い合わせに応じてオーダーを変更することができなければ、キャンセルをすることもある。


 

 ページ構成を決定する

 以下のようなページ構成を考えます。

図1 JSPの構成

 エラー用のページは、ログインページに対してしか記述していませんが、それぞれのページの入力に対して、エラーページが必要であれば明記しておきましょう。ポータルサイトのようにHTMLを複数の小さなポートレットに分割して表示するような場合には、上記のようにシンプルに記述することはできませんが、表示が変わる部分の遷移を明確にしておきましょう。

 ページ自体のデザイン作成はページ構成が決まれば行えます。デザイン会社などを利用して画面デザインを行う場合には、早い段階でHTMLを作成してもらいましょう。

 

 各ページの入力をまとめる

 各ページのフォームの入力をまとめます。入力を受け付ける文字数や型(文字列、数字、日付など)を明確にします。特にデータベースに直接入るものは、文字数の制限などに注意をしましょう。また、顧客登録などで未入力を許す部分などにも注意が必要です。データベースのカラムがnullを許すように設定されているかを確認してください。

 

 各ページの出力をまとめる


 動的に生成するHTML部分を明確にしておきます。検索結果の表示などで、表示行が多い可能性がある場合には、行数制限をするなどの処置が必要です。1つのページにあまり多くのデータ量を表示するとシステムによけいな負荷を与えてしまいます。1ページ当たりの負荷を考えて、画面設計を行うとパフォーマンスで問題が起きる可能性が少なくなります。

 

 ロジックをJavaBeansにまとめる

 JSPには、JavaBeansを利用してロジックを呼び出す仕組みがあります。具体的には、以下のタグを利用することで、JSPからJavaBeansを利用できます。

<isp:useBean id="myJavaBean" class="com.ize.jsp.MyJavaBean" scope="page" >
</isp:useBean>

 このタグとJavaBeansの利用は、JSPのメンテナンス性を向上させるうえでとても重要な機能です。このタグを利用するとmyJavaBeanは、JSPのページ内でJavaのインスタンスとして認識されます。classは、JavaBeansのクラスです。サーブレットエンジンのクラスパスにこのクラスが入っている必要があります。scopeは、以下の値を取ることができます。

  • Page タグが書かれたページ内だけでインスタンスとして保持される
  • Request ほかのJSPページにフォワードしたり、ほかのJSPをインクルードするときに利用する
  • Session HTTPセッションが有効な間、インスタンスとして保持される
  • Application このJSPが含まれるWebアプリケーションの中で利用可能となる

 よって、com.ize.jsp.MyJavaBeanのクラスが以下のようなクラスだった場合に、

package com.ize.jsp.MyJavaBean;

public final class MyJavaBean{
    String name;
  MyJavaBean(){}

  public void setName(String nm){
    name =nm;
  }


  public String getName(){
    return name;
  }
}

となり、JSP内のコードは、

<%
out.println( myJavaBean.getName());
%>

 上記のようにMyJavaBeanクラスの出力をHTMLとして出力することができます。MyJavaBeanにすべてのビジネスロジックを実装して、表示するときに文字列として取り出してHTMLとすれば、JSPに存在するJavaのコードを最小限にすることができます。

 例題では、EJBを利用してデータベースからデータを取得します。よって、このJavaBeansにEJBの参照を保持させておくことで、JSP内からはEJBの利用を意識しないで実装することが可能となります。つまりJSPとEJBは、JavaBeansにより切り離されていることになるのです。

  これにより、JavaBeansを入れ替えることで、EJBを利用しないで直接データベースからデータを取得するように変更を加えたとしても、JSPのコードはいっさい影響を受けることはありません。

  例題では、以下のようなJavaBeansを作成することにします。strutsを採用することが決まっていますが、ここではフレームワークを利用しないでJavaBeansを割り当てます。

com.ize.jsp.CustomerBean 1人の顧客情報を持つJavaBeans。ページをまたがって顧客情報を渡すときに利用する
com.ize.jsp.CustomerSearchBean 顧客の検索を行うJavaBeans。検索結果としてCustomerBeanを返す
com.ize.jsp.ProductBean 1つの商品情報を持つJavaBeans。ページをまたがって商品情報を渡すときに利用する
com.ize.jsp.ProductSearchBean 商品の検索を行うJavaBeans。検索結果としてProductBeanを返す
com.ize.jsp.InvoiceBean 請求書の作成・管理をする機能を実装するJavaBeans

 図2にJavaBeansの利用概要を示します。ページは、sample1.jspからsample2.jspに遷移します。ここで、sample1.jspからsample2.jspに渡したいJavaBeansのインスタンスをHttpSessionに格納します。このときに、sample1.jspであるキーを作成し、そのキーを利用してJavaBeansをsample2.jspにて取り出します。キーは、URLやクッキーを利用して渡します。これにより、JavaBeansを利用してページ間で情報を共有することが可能です。

図2 JavaBeansとHttpSession

 それぞれのJavaBeansがページにどのように利用されるかを以下に示します。矢印上に記述されているJavaBeansがHttpSessionを用いて、ページをまたがって渡されるJavaBeansです。

図3 JavaBeansの利用

 

 カスタムタグライブラリの利用

 JSPは、ユーザーが定義するカスタムタグライブラリをサポートしています。複数のJSP内に埋め込まれるロジックをカスタムタグとして登録すると、JSPのコードがとても見やすいものになります。

 

 ログイン管理について

 J2EEでは、セキュリティの仕組みが用意されています。これは、ユーザーにロールを割り当て、このロールをJSPやWebアプリケーション、EJBなどに適用してセキュリティをかける仕組みです。例えば、例題のプロジェクトではオペレータが各JSPの画面を利用することができます。そこで、オペレータのログインIDにすべてオペレータというロールを割り当てて、そのロールがマッチしているものにだけアクセスを許すという仕組みです。

  ユーザーIDとパスワード、ロールはJ2EEアプリケーションサーバの機能により管理されます。利用するアプリケーションサーバの設定を利用すると、以下のようなフォームで認証を行います。つまり、HTTPのセッションに認証済みのユーザーIDとロールが割り当てられ、Webアプリケーションの仕組みの中で自動的に認証を行うことができるのです。よって、JSPコードの中にユーザーIDなどをチェックするコードを入れる必要はありません。

 

 JSPの実装とstrutsの設定


 ここで、strutsの概要をおさらいします。

図4 struts概要

 Webブラウザは、必ずアクション・サーブレットから各ページにアクセスします。アクション・サーブレットは、以下の2つの設定を持っています。

フォームBeanの登録 フォームBeanの名前とクラス名のマッピングを設定する
アクション・マッピング アクション・フォームBeanの入力チェックを行い、その処理の成功・失敗に応じて、指定したURLへフォワードする一連の流れを設定する

 アクション・クラスから呼び出されるクラスは、以下の2つです。

アクション・フォームBean HTMLのフォームから入力を受け取り、フォーマットのチェックや型のチェックを行うクラスです
アクション・クラス データ取得などの処理を行います。MVCモデルのコントローラの役割を受け持ちます

 前述のロジックをJavaBeansにまとめるでは、strutsを利用しない前提でJavaBeansを設計しましたが、strutsを利用するには、これらのJavaBeansをstrutsのフレームワーク内のクラスに置き換える必要があります。そのプロセスを以下に示します。

 例題のプロジェクトでは、Webブラウザからの入力に以下のようなものがありました。

  • 顧客登録
  • 請求書作成

 よって、2つのアクションフォームBeanを作成することになります。

com.ize.jsp.CustomerForm 年齢が数字で入力されているか、すべての項目が入力されているかなど、入力項目のチェックを行います
com.ize.jsp.InvoiceForm すべての項目が入力されているか、金額が数字で入れられていないかなどをチェックします

 商品情報に関しては、このシステムが入力機能を持たないためにアクション・フォームBeanを作成する必要がありません。ロジックをJavaBeansにまとめるで定義したcom.ize.jsp.ProductBeanをそのまま利用します。

 これら2つのクラスは、入力を行うフォームを持つJSPから次のページへとデータを渡すときにも利用可能です。よって、「ロジックをJavaBeansにまとめる」で定義した2つのJavaBeansと共通機能を持っているので、ここで定義した2つのクラスを利用することにします。

 次にデータを取得するアクション・クラスを作成します。

com.ize.jsp.CustomerRegist 入力された顧客データをデータベースに登録する
com.ize.jsp.CustomerListAction 顧客一覧を取得する。第5回で定義したEJBのうちCustomerBeanを利用して、顧客の一覧を取得する。 実際には、EJBの検索用の機能を用いて一覧を取得する。個々の顧客データはcom.ize.jsp.CustomerFromに格納する
com.ize.jsp.InvoiceRegist 入力された請求書情報をデータベースに登録する
com.ize.jsp.InvoiceListAction 請求書一覧を表示する。第5回で定義したEJBのうちInvoiceManagerBeanを用いて、請求書一覧を取得する。個々の請求書データはcom.ize.jsp.InvoiceFormに格納する
com.ize.jsp.ProductListAction 商品一覧を取得する。第5回で定義したEJBのうちProductBeanを利用して、商品一覧を取得する。実際には、EJBの検索用の機能を用いて一覧を取得する。個々のデータはcom.ize.jsp.ProductBeanに格納する

 以上のアクションフォームBeanとアクション・クラスをstrutsの設定ファイルに登録します。その前に実際のJSPのファイル名を以下に示します。

図5 jspファイル

 strutsの設定ファイルの内容を以下に示します。

<struts-config>

<!-- アクションフォームBeanの登録
<form-beans>
  <form-bean name=" CustomerForm"type="com.ize.jsp.CustomerForm" />
  <form-bean name=" InvoiceForm" type=" com.ize.jsp.InvoiceForm" />
</form-beans>


<!-マッピングの設定
<action-mappings>
  <action path="/customerregist" type=" com.ize.jsp.CustomerRegist" name="CustomerForm" scope="request" validate="true" input="customerregist.jsp">
    <forward name="failure" path="/customerregisterr.jsp" />
    <forward name="success" path="/top.jsp" />
  </action>

  (略)

<action-mappings>


 実際には、top.jspからcustomerregistという文字列をパラメータとして渡されます。アクション・サーブレットはこれを受け取るとまず入力フォームの値をCustomerFormへと入力します。入力チェックが成功していれば、com.ize.jsp.CustomerRegistが呼び出され実際の処理が実行されます。この結果がfailureであればcustomerregisterr.jspへ、成功であればtop.jspに処理がフォワードされます。

 このようにビジネスロジックとページ遷移が完全に分離していますので、ページ間に新しいページを挿入するような場合にはとても簡単にページ構成の変更が可能です。

 

 war、earにまとめる


 J2EEの仕様では、EJBはjarファイルに、Webアプリケーションはwarファイルへとアーカイブします。さらにこれらを1つのアプリケーションとしてearファイルへとアーカイブすることができます。

 J2EEアプリケーションサーバーによっては、earの形式になっていないとデプロイできないものや、すべてのアーカイブ形式のものをデプロイできるものなどがありますので、最終的にどのアーカイブ形式でアプリケーションサーバーにデプロイするかを決めておく必要があります。また、以下のことも考慮に入れましょう。
  • 変更される可能性が高い部分/ページ構成やビジネスロジックで変更の可能性が高いものは、アーカイブとしてまとめておきましょう。もし、変更が生じた場合そのアーカイブだけをデプロイし直せばよいことになります

  • バージョン管理の方針/実装したすべてを1つのバージョンとして扱うのか、部分的にバージョン管理を行うのかを考慮します。バージョン管理の対象ごとにアーカイブを作成すると便利です

 今回で、実際の設計のフェーズは終了です。特に気をつけなければならない部分や資料がないようなところを詳細に説明しました。次回は、J2EEアプリケーションサーバー内のアプリケーションと外部システムの連携のための仕組みを解説します。

■関連記事
連載:Tomcatを使う「JSPプログラミング」
連載:作りながら理解する「JSPコーディング・テクニック」
JavaServlet徹底解説(前編)JSPとどう連携して使うのか
Java Solution FAQ 「JSPの基礎知識と活用」

■参考文献
「わかりやすいUML入門」オーム社
「Webサイトのわかる本」オーム社

プロフィール
樫山友一(かしやま ゆういち)

大手電機メーカー研究所でオブジェクト指向によるシステム開発に従事する。1996年よりJavaへの取り組みをはじめ、J2EEアプリケーションサーバを活用したWebシステム構築のコンサルタントとして多数のプロジェクトを手掛ける。
2001年3月にイーズ・コミュニケーションズ株式会社の設立に参加し、最高技術責任者に就任。
著書に「わかりやすいUML入門」、「Webサイトがわかる本」(いずれもオーム社)がある。


Java Solution全記事一覧



Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間