ブラウザの画面をフレームに分割するには、HTMLのFRAMEタグの代わりにuji:frameタグを使用してフレームを定義します。uji:frameタグを使うことにより、FRAMEタグに比べ以下の利点があります。
JSPの構成が簡潔になります。
フレームの表示更新をビジネスクラスで指示できます。
リクエストがフレームごとに検証されます。
フレーム更新中のリクエストが防止できます。
アプリケーションでフレームを利用するには、画面を以下のように作成してください。
フレームセットを定義する制御ページを作成します。この制御ページでは、FRAMESETタグとuji:frameタグでフレームの分割方法を定義します。
フレームごとに制御ページを作成します。この制御ページは、各フレームで使用する領域名と領域の分割方法を定義します。
フレームに表示する入出力ページでフォームを使用する場合は、HTMLのFORMタグの代わりにuji:formタグを使用します。
フレームと制御ページの対応関係は以下の図のようになります。
サブウィンドウを使ったアプリケーションと同様に、フレームもcom.fujitsu.uji.http.WindowControllerクラスとcom.fujitsu.uji.http.Windowクラスによって管理されます。各フレームにそれぞれWindowオブジェクトが対応し、updateメソッドでフレームの表示更新が行えます。サブウィンドウの利用法方は、“14.6 ウィンドウの制御”を参照してください。
注意
フレーム制御機能を使用した場合、ブラウザにおけるフレーム名(HTMLのFRAMEタグのnameアトリビュートで指定される名前)はApcoordinatorが設定します。Apcoordinatorがブラウザに設定するフレーム名は、com.fujitsu.uji.http.WindowクラスのgetIdメソッドで取得できます。
フレーム制御機能と初期化パラメタuji.model.viewNameを併用することはできません。
JSPの作成
フレームセットを定義する制御ページの作成
一般にHTMLではFRAMESETタグとFRAMEタグでフレームを定義しますが、ApcoordinatorアプリケーションではFRAMEの代わりにuji:frameタグを使用します。フレームには名前を付け、uji:frameのnameアトリビュートで指定します。フレーム名を付ける際には以下に注意してください。
フレーム名はアプリケーション内で一意になるように設定してください。例えば、複数のウィンドウをフレーム分割している場合は、他のウィンドウのフレームも含めて全フレームが異なる名前になるようにしてください。
フレーム名はどのウィンドウの名前とも重複しないようにしてください。また、メインウィンドウの名前である"main"をフレーム名として使用することはできません。
各フレームで使用する制御ページのURLをuji:frameタグのsrcアトリビュートで指定します。フレームセットを定義する制御ページには、uji:dispatchタグとuji:windowControlタグも記述してください。uji:includeタグは使用しません。以下は記述例です。
<%@ page contentType= "text/html; charset=shift_jis" %> <%@ page errorPage="ErrorPage.jsp" %> <%@ taglib uri="uji-taglib" prefix="uji" %> <HTML> <HEAD> <TITLE>予約システム</TITLE> <uji:dispatch /> <uji:windowControl/> </HEAD> <FRAMESET rows="50%,*"> <uji:frame src="mainFrm.jsp" name="mainFrame"/> <uji:frame src="navFrm.jsp" name="navFrame"/> <NOFRAMES> フレーム対応のブラウザをご使用ください。 </NOFRAMES> </FRAMESET> </HTML>
uji:dispatch, uji:windowControlはこの順番で、HEADタグのコンテントに記述します。
各フレーム用の制御ページの作成
通常の制御ページと同様にuji:dispatchタグとuji:includeタグを使うのに加え、さらにuji:windowControlタグも記述してください。以下は記述例です。
<%@ page contentType= "text/html; charset=shift_jis" %> <%@ page errorPage="ErrorPage.jsp" %> <%@ taglib uri="uji-taglib" prefix="uji" %> <HTML> <BODY> <uji:dispatch /> <uji:include pane="mainHeader" /> <uji:include pane="mainBody" /> <uji:windowControl/> </BODY> </HTML>
uji:windowControlはuji:includeの後、</BODY>の前に記述します。
uji:frameタグを使用する場合、画面の更新を行うためにはリクエストをJSP(制御ページ)で受け取るようにアプリケーションを作成してください。リクエストをサーブレットで受け取り、レスポンスとして画面(JSP)を返した場合、uji:frameタグは使用できません。
フレームの表示
メインウィンドウをフレーム分割する場合
フレームセットを定義した制御ページのURLを、アプリケーションのURLとして使用します。例えば、main.jspという名前でフレームセットを定義した制御ページを作成し、アプリケーションのURLとして、http://yourHost/contextPath/main.jsp をアプリケーションのURLとして使用します。
アプリケーション実行開始時に呼ばれるビジネスクラスのメソッドでは、各フレームで使う領域にそれぞれデータBeanを割り当てます。以下の例は、画面を2つのフレームに分割し、片方で領域mainHeaderとmainBodyを、もう一方で領域navBodyを使う場合の記述です。
public void startup(DispatchContext context) { context.setResponseBean("mainHeader", new HeaderBean(), true); context.setResponseBean("mainBody", new BodyBean(), true); context.setResponseBean("navBody", new MenuBean(), true); }
フレームの領域にデータBeanを割り当てる場合は、setResponseBeanの第3引数にtrueを指定してください。
サブウィンドウをフレーム分割する場合
サブウィンドウで、フレームセットを定義した制御ページを使用すると、サブウィンドウがフレーム分割されます。サブウィンドウで使用する制御ページは、Windowクラスのopenメソッドで指定します。openメソッドについては、“14.6 ウィンドウの制御”を参照してください。
import com.fujitsu.uji.http.Window; import com.fujitsu.uji.http.WindowController; import com.fujitsu.uji.http.HttpDispatchContext; ... public void someHandler(DispatchContext context, MyDataBean dataBean) { WindowController wCtrl = ((HttpDispatchContext)context).getWindowController(); Window subWin = wCtrl.createWindow("subWindow"); subWin.open("frame.jsp","resizable=yes,width=300,height=300"); // (1) context.setResponseBean("subHead", new SubHeadBean(),true); // (2) context.setResponseBean("subBody", new SubBodyBean(),true); // (2) ... }
(1) サブウィンドウを開くときに、フレームセットを定義した制御ページのURLを指定します。このURLはコンテキストルートからの相対パスです。
(2) 各フレームで使用される領域にそれぞれデータBeanを割り当てます。このとき、setResponseBeanの第3引数にtrueを指定してください。
フレームの表示の更新
通常は、フォームが送信されるとそのフォームが表示されているフレームが更新されます。他のフレームを更新したい場合するには2通りの方法があります。
更新するフレームをビジネスクラスで指定する場合
ビジネスクラスで、フレームの表示更新を指示します。この方法では、com.fujitsu.uji.http.WindowControllerクラスと、com.fujitsu.uji.http.Windowクラスを使用します。
import com.fujitsu.uji.http.Window; import com.fujitsu.uji.http.WindowController; import com.fujitsu.uji.http.HttpDispatchContext; ... public void someMethod(DispatchContext context, MyDataBean dataBean) { WindowController wctrl=((HttpDispatchContext)context).getWindowContrller(); // (1) Window frame=wctrl.getWindow("mainFrame"); // (2) frame.update(); // (3) context.setResponseBean("mainHeader",new HeaderBean(), true); // (4) context.setResponseBean("mainBody",new BodyBean(), true); // (4) }
(1) WindowControllerクラスをHttpDispatchContextクラスから取得します。
(2) 更新するフレームに対応するWindowオブジェクトを、WindowControllerクラスからgetWindowメソッドで取得します。getWindowの引数には更新するフレームの名前を指定します。
(3) (2)で取得したWindowオブジェクトのupdateメソッドを呼び出します。
(4) 必要なら、更新するフレームで使用している領域にデータBeanを割り当てます。このとき、setResponseBeanの第3引数にtrueを指定してください。割り当てるデータBeanのオブジェクトが前回表示時と同じなら、この処理は不要です。
この方法の場合、updateメソッドで更新を指示したフレームのほかに、フォームが表示されていたフレームも更新されます。
更新するフレームをJSP中で指定する場合
更新するフレームの名前をuji:formタグのtargetWindowアトリビュートで指定します。また、更新するフレームの制御ページをactionアトリビュートで指定します。これにより、フォームが送信されたときに、そのフォームのあるフレームは更新されず、targetWindowで指定したフレームが更新されます。
<uji:form name="updateForm" targetWindow="mainFrame" action="mainFrm.jsp"> ... </uji:form>
更新するフレームの各領域には、必要に応じてデータBeanを割り当てます。この処理は、フォーム送信時に呼び出されるビジネスクラスのメソッドで行います。以下はビジネスクラスのメソッドの記述例です。
public void someMethod(DispatchContext context, MyDataBean dataBean) { context.setResponseBean("mainHeader",new HeaderBean(), true); context.setResponseBean("mainBody",new BodyBean(), true); }
setResponseBeanの第3引数にはtrueを指定してください。割り当てるデータBeanのインスタンスが前回表示時と同じなら、setResponseBeanの呼び出しは不要です。
全フレームの表示を更新する場合
フレーム分割しているウィンドウの表示を更新することにより、フレームセットに含まれるすべてのフレームの表示が更新されます。ウィンドウの表示を更新するには、 Windowクラスのupdateメソッドを使用します。
public void someMethod(DispatchContext context, MyDataBean dataBean) { WindowController wctrl=((HttpDispatchContext)context).getWindowContrller(); // (1) Window win=wctrl.getWindow("main"); // (1) win.update(); // (2) context.setResponseBean("mainHeader",new HeaderBean(), true); // (3) context.setResponseBean("navBody",new MenuBean(), true); // (3) }
(1) WindowControllerを取得し、フレーム分割しているウィンドウのWindowオブジェクトを取得します。getWindowの引数にはウィンドウ名を指定します。
(2) (1)で取得したウィンドウのupdateメソッドを呼び出し、表示更新を指示します。
(3) 必要なら、更新するフレームで使用している領域にデータBeanを割り当てます。このとき、setResponseBeanの第3引数にtrueを指定してください。割り当てるデータBeanのオブジェクトが前回表示時と同じなら、この処理は不要です。
注意
全フレームの表示を更新した場合、リクエストを出したフレームが2回更新されるため、画面がちらついて見える場合があります。これを防止するためには、更新したいフレームだけ指定してください。
フレーム更新中のリクエストの防止
uji:frameタグを使用した画面を表示させると、各フレームの中を表示させるために、フレームの数だけリクエストが発生します。このとき、全てのフレームの表示が同時に完了するのではなく、一部のフレームの表示が遅れる場合があります。この状態でも表示済みのフレームのボタンやリンクはユーザーが操作できる状態にあるため、一部フレームの表示が未完了な状態で次のリクエストが送信される可能性があります。このようなリクエストの実行を防止するには、uji:frameタグのsyncアトリビュートにtrueを指定します。
<FRAMESET rows="50%,*"> <uji:frame src="mainFrm.jsp" name="mainFrame" sync="true"/> <uji:frame src="navFrm.jsp" name="navFrame" sync="true"/> <NOFRAMES> フレーム対応のブラウザをご使用ください。 </NOFRAMES> </FRAMESET>
上記例の場合、mainFrm.jspとnavFrm.jspの表示が完了するまで、mainFrame, navFrameから送信されたリクエストに対しては空のレスポンス (HTTPのステータスコード204) が返されます。この結果、ビジネスクラスは呼び出されず、画面の表示も更新されません。この機能は、sync="true"を指定したフレームの間でだけ働きます。一部のフレームにsync="true"を指定しなかった場合、そのフレームからのリクエストは常に実行されます。また、そのフレームの表示が完了するのを、sync="true"が指定されたフレームは待ちません。
一定時間待っても表示が完了しなかった場合は、タイムアウトとなり本機能は自動的に解除され、表示未完了のフレームがあってもリクエストが処理されるようになります。これにより、ブラウザの停止ボタンが押された場合など、フレーム表示のためのリクエストが送信されなかった場合に、フレームからのリクエストが全く受け付けられなくなってしまうのを防ぎます。タイムアウトまでの時間はデフォルトで10秒です。この時間を変更するには初期化パラメタuji.frameSyncTimeoutにタイムアウトまでの秒数を設定してください。0を指定するとタイムアウトしません。
リクエストの検証
フレームを使用したアプリケーションでも、HttpControlStateProfileクラスとuji:controlStateタグを使用することにより、リクエストを検証することができます。リクエストの検証については、“15.1.8 リクエストの検証”を参照してください。
フレームを使用したアプリケーションの場合は、フレームに表示されるフォームそれぞれにuji:controlStateタグを記述します。正当性はフレームごとに検査されます。それぞれのフレームにおいて、最後に表示された画面からのリクエストが「正当な」リクエストとして扱われます。