useBean - みる会図書館


検索対象: UNIX MAGAZINE 2002年5月号
9件見つかりました。

1. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages— public void init ( 引数 1 , 引数 2 , public Abc() 引数 1 , 引数 2 , ・・・に関する処理 Abc クラスを呼び出す JSP ページの書き方の違いもみ てみましよう。 もとの引数付きのコンストラクタの場合、 jsp:useBean タグは利用できないので、オプジェクトを作るときにはス Abc d = new Abc( 引数 1, 引数 2 , く % クリプトレットを使います。 プジェクトを作る JSP のスクリプトレットのコードは次 作り替えた JavaBean 版の Abc クラスを使うと、オ d. init ( 引数 1 , 引数 2 , Abc d = new Abc(); く % のようになります。 124 •-s jsp:useBean の本体をスクリフ counter2. jsp のように スするメソッドとして書き換えられるのなら、図 6 の もし、 init() メソッドの部分をプロバティにアクセ く /jsp:useBean> d. init( 引数 1, 引数 2 , く % く Jsp:useBean id="d" c1ass="Abc" scope= Bean タグを使って書き換えると、次のようになります。 そこで、上記のスクリプトレットのコードを jsp:use- か、あるいはこれらの組合であってもかまいません。 ・文字列 ・ HTML のタグ ・式タグ ・スクリプトレット 体に言当する内容は、 体に jsp:setProperty タグを使っていますが、タグの本 図 6 の counter2. jsp の例では jsp:useBean タグの本 トレットではなく、 jsp:setProperty などのプロバティを 操作するタグに置き換えることもできます。 また、 く Jsp:useBean id="d" cIass="Abc" scope="session" > く b > セッション開始 ! く /b> く br> d. init( 引数 1, 引数 2 , く % 排イ也処理 ザに表示します。 セスしたときだけ、 く /jsp:useBean> セッション開始 ! " の文字列をプラウ のような JSP コードは、同一のセッションて初めてアク readCounter() で読み込んだ値が、、 1 " だったとします。 たとえは、 1 人目のユーサーがアクセスしたときに return count ; saveCounter (count) ; C ount 十十 ; return count ; if ( (count=readCounter ( ) ) くの { int count ; public int getVa1ue ( ) コードを見てみましよう。 ここでもう一度、 Counter2 の getValue() メソッドの クラスの処理か 1 司時に実行されます。 のページに複数の人が同時にアクセスすると、 Counter2 セス要求を並列に処理します。したがって、 counter2 ・ jsp 通常、 Web サーバーは受け取った Web ページへのアク きるのか JSP ページに同時にアクセスしたとき何が起 ります。 も Web のプログラミングにありがちな大きな不具合があ ここて紹介した 2 不鶤頁のアクセスカウンタには、いずれ によって 1 人目のカウンタ値は、、 2 " になります。 count 十十・ すると、 UNIX MAGAZINE 2002.5

2. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages—O 図 6 アクセスカウンタを呼び出す JSP ファイル (counter2 ・ jsp) く % page contentType="text/htm1 ; charset=EUC-JP" % > く % page import="counter. * " % > く ! DOCTYPE HTML PUBLIC " -//W3C//DTD HTML 4 . 0 Transitiona1//EN"> く html> く head> く meta http—equiv="Content—Type" content="text/html ; charset=EUC¯JP"> く tit1e>JavaBean 版カウンタ ( その 2 ) く / title > く /head> く body> く Jsp:useBean class="counter. Counter2" scope= application' > く jsp:setProperty property="file" va1ue="/usr/10ca1/tomcat¯4.0.3/var/AccessCounter' く /jsp:useBean> アクセス数 : く j sp : getProperty name="ac " property="value" / > く /body> く /html> く jsp:useBean 本体・・・ く /jsp:useBean> UNIX MAGAZINE 2002.5 く」 sp : getproperty name="ac " property="value'i / > ウントするための処理を呼び出さなくても、 のなかでアクセス数を更新しているので、アクセス数をカ 今回の JavaBean のコードは、 getValue() メソッド おいてください。 存先のファイルは事前に用意して初期値 0 を設定して ファイルのパスを指定しています。なお、アクセス数の保 グをすることで、オプジェクトの生成時に 1 度だけ 図 6 では、 jsp:useBean の本体に jsp:setPropertY タ すればよいことになります。 ルのパスは、オプジェクトを生成したときに 1 度だけ定 はありません。したがって、アクセス数の保存先のファイ 目のアクセスかによって、言求するファイルを変えること に同しファイルに言当求することを前提としています。舸 Counter2 のアクセスカウンタでは、アクセス数をつね れません。 行さそれ以後は JSP ページにアクセスしても実行さ 後、最初に JSP ページにアクセスしたときに 1 度だけ実 コープをもっオプジェクトの場合、 Web サーバーの起動 るときに 1 度だけ実行されます。つまり、 application ス 置くことかできます。このコードはオプジェクトを生成す のように、開始タグと終了タグのあいだに本体のコードを によって、現在 ( 更新後 ) のアクセス数が表示されます。 Java クラスを JavaBean に作り替える Java で作ったクラスを jsp:useBean タグで呼び出せ るようにするには、引数をもたないコンストラクタが必要 です。引数付きのコンストラクタをもつ Java クラスを JavaBean として扱いたい場合は、コンストラクタを作り public Abc( 引数 1, 引数 2 , たとえば、 替える必要があります。 を実行する init() メソッドに分けることができれば Java ー のような引数をもたないコンストラクタと、初期化の処理 たとえば、さきほどの引数付きのコンストラクタを、次 に分解します。 メソッド ・もとのコンストラクタでおこなっていた処理を実行する ・引数をもたないコンストラクタ ストラクタを、 ます。このクラスを JavaBean にするには、もとのコン のようなコンストラクタをもつ Abc クラスがあったとし Bean の出来がりです。 123

3. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages—@ 図 11 sleep() を追加した不具合を修正しているコード public int getVa1ue ( ) int c ount synchronized (this) { if ( (count=readCounter() ) return count ; count 十十 ; try { Thread. sleep ( 5000 ) ; } catch (Exception e) { saveCounter (count) ; return C ount ; 図 13 jsp:useBean タグの非他タ里 くの { 図 12 正しく表示されたアクセスカウンタ ムファイル ( E ) 編集 ( 印表示検常 ) ジャンプ 0 ブッりマり ( 印タスりヘルプ旧 ) 物匪仮カウンタ ( その 4 ) ー Netscape 5 ロロ雪コュメ : 完了 00 け ) リアクセス数 : 64 排他虹理を行っているカウンタ 、働ホーム、検常ロカりマーり、 t 師物 536 ”、新着、お都助、メントズ 方イル住編果 ( 印表示検索ジャンプ 0 ブッりマーり ( 印タスクへルプ ( 印 アクセス数 : 63 排他処理を行っているカウンタ 」木ーム検索朝ブッりマーり第物引聞ー鷭。、新著籌お都助、メントズ ロ X ロ X / / begin [file="/counterl . jSP";fr0m=(11,0);t0=(11,66)] counter . Counter1 ac Ⅱ u11 ; -jspx-specialac true ; ← true なら jsp:useBean の本体の処理を実行する if ( ac = Ⅱ u11 ) { pageContext . getAttribute ( "ac" ,PageContext. APPLICATION—SCOPE) ; ac= (counter . Counterl) synchronized (application) { false; boolea 取 -Jspx—specialac (counter. CounterI) java. beans . Beans . instantiate(this . getCIass() . getCIassLoader() , "counter . Counter1") ; pageContext . setAttribute ( ac , すると、別々のアクセスによって実行される 2 系統の処 理の両方が、 getAttribute() で null を受け取ります。次 の if 文のなかのコードも重複して実行さ新しく生成さ れた 2 つのオプジェクトが、 pageContext 内に同し名前 て保存されます。 その結果、 ・アクセス回数を 1 回数えそこなう ・ jsp:useBean の本体の処理が 2 回実行されてしまう ・生成した 2 つのオプジェクトの一方しか保存されない ( 最初に保存されたオプジェクトは 2 番目に保存された オプジェクトに上書きされて失われる ) といったさまざまな問題カ吽します。 UNIX MAGAZINE 2002.5 PageContext . APPLICATION_SCOPE) ; このように、 Web のアプリケーションでは処理か並列 に実行されることを ; 頁におき、共通のデータを読み書き するときは必要に応して排他処理を組み込まなくてはなり ません。 ☆ 今回は、 JavaBean を生成する jsp:useBean タグのす こし詳しい説明から発展して、 JavaBean オプジェクト のスコーフ。や jsp:useBean の実装を解説しました。また、 Web アプリケーションの典型的な不具合として、 JSP ペ ージに対して同時に複数のアクセスが発生した場合の動作 をとりあげ、正しく処理をおこなうための排他処理とその 具ー勺なガ去を紹介しました。 ( あらい・みちこ ASTEC) 127

4. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages—O jsp:useBean タグに文寸応する Java のソースコード 図 4 1 / / begin [file="/counterl . jSP";fr0m=(11,0);t0=(11,66)] counter. Counter1 ac = Ⅱ u11 ; 2 boolean —jspx—specialac = false; 3 synchronized (application) { 4 ac= (counter . Counterl) 5 pageContext . getAttribute ( "ac" ,PageContext . APPLICATION-SCOPE) ; 6 if ( ac = null ) { 7 ー」 spx—specialac 8 try { 9 10 true ; (counter. Counter1) java. beans . Beans. instantiate(this. getC1ass() . getC1as sLoader ( ) , 'counter . Counterl") ; } catch (C1assN0tFoundException exc) { throw new InstantiationException(exc. getMessage ( ) ) ; } catch (Exception exc) { throw new Serv1etException ( " Cannot create bean Of class " + " counter. Counter 1 亠、 1 イ 1 イ上 exc) ; pageContext . setAttribute("ac" 15 16 17 18 if (—jspx—specialac 19 20 / / end 21 / / begin [file="/counterl . jsp";from=(11,0) ; t0 = ( 11 , 66 ) ] 22 23 / / end jsp:useBean の実装 (Tomcat 4.0.3 ) というメソッドが返すイ直が設定されます。 pageContext は、 JSP ページに関連した情報を提供するオプジェクト jsp:useBean タグの部分が、 JSP 工ンジンで実行され で、 1 月号で説明した暗黙オプジェクトの pageContext るときにどのような Java のソースコードに変換されるの そのものです。ここでは、 pageContext に保存されてい かみてみましよう。図 4 は、 counterl. jsp の、 る、、、 ac" という名則の application スコープをもつオプ ジェクトを返しています。 く jsp:useBean class="counter. scope="application" / > pageContext にオプジェクトを保存しているのは、も うすこし先の 16 行目のコードです。 の部分に対応する Java のソースコードです。 pageContext . setAttribute ( " ac , PageContext . 2 行目で定義している counter ℃ ounterl クラスの変 APPLICATION_SCOPE) ; 数 ac は、 JSP ページの jsp:useBean で定義した ac オ setAttribute() は getAttribute() の逆の操作にあた プジェクトを表しています。 り、 ac オプジェクトに、、 ac " という名前を付け、 appli- 5 ~ 6 行目では、アクセスカウンタのオプジェクトが保 cation スコープをもつオプジェクトとして pageContext 存されていれば、それを ac 変数に設定しています。ただ に保存しています。 し、初めて JSP ページにアクセスしたときには、まだア 初めて JSP ページにアクセスしたときには、 5 ~ 6 行目 クセスカウンタ・オプジ - ェクトが保存されていないため、 で ac 変数に null か轂定されるので、 7 行目の if 文の中 ac 変数には null か設定されます。 身か実行されます。 if 文のなかでは、アクセスカウンタ・ この処理をもうすこし詳しく追ってみましよう。 ac 変 オプジェクトを生成して ac 変数に設定しています。 数には 6 行目の、 オプジェクトの生成に見慣れないガ去カイ吏われています れ 10 行目の、 pageContext . getAttribute ( "ac " ,PageContext . APPLI (counter. Counter1) java. beans . Beans. instan CATION_SCOPE) ; ac , PageContext . APPLICATION—SCOPE) ; true) { 120 UNIX MAGAZINE 2002.5

5. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages— tiate(this. getC1ass() . getC1assLoader() , r. Counter1") ; は、 Beans クラスの instantiate() メソッドを使って、 counter ℃ ounterl クラスのオプジェクトを生成していま す。このコードは、クラスか存在しないなどの理由でオプ ジェクトの生成に失敗したときに、コンパイルエラーでは なく例外か発生することを除けは次のコードと同じです。 ac = new counter. Counterl() ; アクセスカウンタ・オプジェクトの生成に成功すると、 16 行目に制御が移り、生成したオプジェクトを page- 'counte ・ setAttribute() ・ getAttribute() です。ただし、 定した場合でも、変換後の Java の実装は基本的には同し jsp:useBean タグで application 以タトのスコ プジェクトは次回以降のアクセスで参照されます。 Context に保存します。すでに説明したとおり、 ープを指 このオ 今回はファイルの入出力処理を含むため、 Counter1. java 保存する Java のソースコード、、 Counter2. java" です。 図 5 は、ファイルを利用してアクセスカウンタの値を アクセスカウンタ JavaBean ( その 2 ) スカウンタを作り、 JSP ファイルから呼び出してみまし るために、アクセス数をファイルに保存するようなアクセ 保存していたアクセス数を忘れてしまいます。これを避け ト述のアクセスカウンタは、 Web サーバーを止めると ファイルを利用したアクセスカウンタ スコープになります。 に渡すスコーフ窈旨定が、 jsp:useBean タグて指定された UNIX MAG AZINE 2002.5 ・ value プロバティの値を取得するメソッド (getVal- ・用 e プロバティの値を設定するメソッド ・引数をもたないコンストラクタ Counter2 クラスは、 よりはすこし複雑です。 (setFile()) をもつ JavaBean です。 setFile() は、アクセス数尉寺するファイルのパスを 設定するメソッドです。引数として渡されたファイルのパ スは counterFiIe 変数に保存さアクセス数の取得など の目的でファイルにアクセスするときに参照されます。 getValue() はファイルに保存されていたアクセス数 ではなく、現在 ( 更新後 ) のアクセス数を返します。 get- Value() の内部では次の処理をおこないます。 1. readCounter() を呼び出し、ファイルに保存されてい たアクセス数を count 変数に設定する。 2. readCounter() はエラーの発生時には負の値を返すの で、その場合はそのままメソッドを抜ける。 3. count 変数の値を 1 増やし、今回のアクセスぶんをア クセス数に反映させる。 4. saveCounter() を呼び出し、更新後の ( 新しい ) アクセ ス数をファイルに保存する。 5. メソッドの戻り値として更新後のアクセス数を返す。 アクセス数をファイルから読み込んだり、ファイルに 保存する処理は、 readCounter() と saveCounter() で おこなっています。 readCounter() のコードを追ってみましよう。 read- Counter() では counterFile をオープンし、読み込んだ 値か数字列であればその値を返します。 counterFile の読 込みに失敗したり、数字 : 列以外の値が保存されている場合 には、言ムみに失敗したことを意味する負の値 ( ー 1 ) を返 します。 saveCounter() のコードでは、 counterFile を書込み 用にオープンし、引数として受け取ったアクセス数を書き 込んでいます。 こまでで、アクセスカウンタ JavaBean の処理は理 解できたでしようか。続いて、この JavaBean を呼び出 す JSP ファイルについてみていきます。 jsp:useBean タクの本体 図 6 は、アクセスカウンタとして Counter2 クラス を使う JSP ファイル、、 counter2. jsp" です。これまでみ てきた jsp:useBean タグとの大きな違いは、タグに本体 ( b 。 dy ) があることでしよう。 jsp:useBean タグは、 121

6. UNIX MAGAZINE 2002年5月号

連載 /OavaServer Pages—・ 図 2 アクセスカウンタを呼び出す JSP ファイル (counterl ・ jsp) く %@ page contentType="text/htm1 ; charset=EUC—JP" % > く %@ page import=" counter. * " % > く ! DOCTYPE HTML PUBLIC "—//W3C//DTD HTML 4 . 0 Transitiona1//EN"> く html > く e ad> く meta http—equiv="Content—Type" content="text/html ; charset=EUC¯JP"> アクセス数 : く j sp : getProperty name="ac" property="value" / > く」 sp : setproperty name="ac" property="value" value=" 1 " / > く Jsp:useBean class="counter. Counter1" scope="application' く body> く /head> く tit1e>JavaBean 版カウンタ ( その 1 ) く / title > く /body> く /html> 図 3 counterl. jsp の表示 ・秘」みき E をョれカウノタ 1 ) ー第 ! をも 属生です。 ントは、 counterl. jsp 内の jsp:useBean タグの scope 実装したアクセスカウンタか重川乍するための大切なポイ セス数が表示されます ( 図 3 ) 。 CounterI オプジェクトの内部でカウントアップしたアク ロ 9 ー雪、第↓物 : 発ア ( 0 社物 デフォルトである page スコープになります。 コープを指定できます。 scope 属性を省略した場合には、 jsp:useBean タグの scope 属生には、次の 4 不頁のス scope 属性 トのスコープになります。 ンに属しているべージおよひ時間の範囲が ac オプジェク を設定したので、この JSP ページと同しアプリケーショ Counter1 のオプジェクト ac に application スコープ scope="application" / > く Jsp:useBean class="counter. C0u取teて1” アクセス数 : 14 ふ木ーム検常ロプ必マーク、いを t を 3 弊。新著、お動助、メンバーズ . ファイルの編集 ) 表示 ( Y ) 検常 6 ) シャンプゆカクマーり⑧タスりヘルプせ ・ request ・ page UNIX MAGAZINE 2002.5 ・ sesslon ・ application オプジェクト内のカウンタ値は 1 すっ増え、アクセス回数 たがって、 setValue() メソッドか呼び出されるたびに ac 値は初期化されす、以前の値がそのまま残っています。し クトを参照します。オプジェクトが一尉寺しているカウンタ は、新しいオプジェクトを生成せすに、既存の ac オプジェ が停止するまで存在し続けます。 2 回目以降のアクセスで いったん生成された ac オプジェクトは、 Web サーバー はオプジェクトの生成時にネ騏月化されます。 に生成されます。オプジェクトかイ尉寺しているカウンタ値 起重圻幻こ初めて counterl. jsp ページにアクセスしたとき ac オプジェクトは、 Web サーバー (JSP 工ンジン ) の 重川乍は次のようになります。 コープを設疋しています。この場合、 ac オプジェクトの counterl. jsp では、 ac オプジェクトに application ス ・ application : JSP のアプリケーションか有効な囲 ・ session : セッションか有効な範囲 た場合には、そのページの範囲もスコープに含まれる ディングなどでリクエストが別の JSP ページに送られ ・ request : HTTP のリクエストか有効な用。フォワー ・ page : JSP ページか有効な範囲 オプジェクトのスコープと同しです。 これら 4 つのスコープの意味は、 2 月号で説明した暗黙 が寺されます。 119

7. UNIX MAGAZINE 2002年5月号

JavaServer Pages 荒井美千子 JavaBeans の利用 ( 2 ) 前回、 Tomcat 4.0.2 がリリースされたことを紹介し ましたが、皆さんが先月号を手にしたころにはすでに新し いバージョンがリリースされていました。 Tomcat 4.0.2 にはリモートからサーバー上の任意のファイルを読めるよ うなセキュリティ上の脆弱生が発見されたため、 2002 年 3 月 1 日に Tomcat 4.0.3 がリリースされました。もし Tomcat 4.0.2 を使っているようなら、 4.0.3 に入れ替え ることをお勧めします。 さて、前回はログインページのサンプルを使って、 JSP ページから JavaBean を使うガ去を説明しました。今回 は、 JavaBeans との付合い方をもうすこし深く知ってい ただきます。また、 JavaBean を作ったり使ったりする ときのちょっとしたテクニックや、注意点なども説明し ます。 JavaBean のスコープ 前回の jsp:useBean" タグの解説では詳しい説明を省 きましたが、このタグには scope 属生を指定できます。 jsp:useBean タグで生成した JavaBean オプジェクトは、 scope 属生て指定されたスコープをもつようになります。 最初にスコーフ窈旨定を利用して、 JavaBean 版のアク セスカウンタを作ってみましよう。 アクセスカウンタ JavaBean ( その 1 ) 図 1 は、 Java で作ったアクセスカウンタ・クラスのソ ースコード、℃ ounterl. java" です。このクラスは Java- 118 ・ va ⅲ e フロノヾテイへのアクセスメソッド ・引数をもたないコンストラクタ Beans のイ兼である、 図 1 スコープを不堋したアクセスカウンタのソースコード (Counter1 ・ java) package counter ; public class CounterI { private int value = 0 ; public Counter1() { } public int getVa1ue ( ) return value ; public void setVaIue(int v) value 十 =v ; UNIX MAGAZINE 2002.5 counterl. jsp" です。このページにアクセスするたびに プジェクトを使ってアクセス数を表示する JSP ページ 図 2 は、 Counter 1 クラスのアクセスカウンタ・オ JavaBean のスコープを指定する ドで取得できます。 value 変数に保存したカウンタ値は getValue() メソッ アクセスカウンタの増研直を渡すイ」にしています。 こでは JSP ページの処理を簡単にするために、引数で 引数で指定された値をプロバティに設定します。しかし、 はプロバティ値を設定するためのメソッドで、一般には VaIue() を呼び出すたびに増えていきます。 setVaIue() ue " 変数にイ尉寺します。この変数は 0 にネ加月化され、 set- Counter1 クラスでは、アクセスカウンタの値を、、 val- 使っていません。 をもっていることを除けば、特別なテクニックはいっさい

8. UNIX MAGAZINE 2002年5月号

連載 /JavaServer Pages—O 図 9 sleep() を追加した不具合のあるコード public int getVa1ue ( ) int count return count 十十 ; try { Thread . sleep ( 5000 ) ; count ; if ( (count=readCounter()) return count ; saveCounter (count) ; } catch (Exception e) { くの { 図 10 counter3. jsp の表祚果 上日 n 版カウンタにの 3 ) ー Netscape 6 ードの E'•をな 1 ′第を ロロコ讐 1 めト : 発 7 ( 5 物前 アクセス数 : 60 排他処理を行っていないカウンタ ホム検索ロプめマーり、を“ 0 籌新着、お勧め、メンバーズ 0 - ファイル ( E ) 編集 ( 日表示検索ジャンプ 0 ブックマーク ( 印タスク (I) ヘルプ ( 印 ーホーム検素うカクマゆ、いを” 0 新着・、おを籌メントオ ~ ファイルの編集 ( 印表示検索ジャンプ 0 プめマーり ( 印タスクヘルフ凹 ロ。ー : ~ ュメント : 発了 ( 5 物 アクセス数 : 60 排他処理を行っていないカウンタ 第同 plication 以外のスコープをもつ場合は、 1 人目のアクセ スと 2 人目のアクセスで、、 this " の実体が違うかもしれな いので、ロックするオプジェクトには別のものを選ぶ必要 排他里の確認 があります。 126 サから 5 秒以内に連続して counter3. jsp にアクセスする を使った、、 counter3. jsp" の表示結果です。 2 つのプラウ 図 10 は、図 9 のコードを組み込んだアクセスカウンタ 示されるはすです。 る不具合が発生し、 1 回目と 2 回目で同じアクセス数カ俵 あいだに別のアクセスが発生すると、アクセス数を間違え この細工によって、アクセス数を処理している 5 秒の 日判勺に停止 ) するようにしました。 Counter() メソッド ) の直前で、 5 秒澗 sleep ( 処理を一 ッドです。ファイルにカウンタ値を保存する処理 (save- 図 9 は、排他処理をおこなっていない getVaIue() メソ まずは、不具合が発生するほうのコードに細工しましょ することです。 し細工し、現象カ起きやすいようにしたうえて動作を石忍 このようなケースでの常套手段は、ソースコードにすこ のか容易には石忍できません。 は、ソースコードの不具合を修正しても正しく動いている うかがタイミングに依存し、現象を再現しにくいケースで アクセスカウンタの例のように、不具合が起きるかど ましよう。 排他処理か期待どおりに動いているかどうか確かめてみ と、図のようにアクセス数か 1 司しになります。 図 11 は、排他処理をおこなったうえで 5 秒間 sleep するようにした getValue() メソッドです。このアクセ スカウンタのコードでも、 1 回目のアクセスから 5 秒以 内に 2 回目のアクセスがあると、同し時刻 ( 時間帯 ) に getValue() の実行か重複します。しかしこのケースでは、 あとからコードを実行しようとしたアクセスが synchr 。ー nized のプロックの直前て待たされます。 その結果、 1 回目のアクセスがファイルにアクセス数を 書き込んだあとでないと、 2 回目のアクセスはファイルか らアクセス数を読みにいかないので、アクセス数は正しく カウントされます。結果として、 2 つの Web プラウサ上 にはそれぞれがアクセスした時点のアクセスカウンタの値 が正しく表示されます ( 図 12 ) 。 Jsp:useBean のお也里 排他処理は、 jsp:useBean を変換した Java プログラ ムのなかでもおこなわれています。 図 13 は、図 4 と同じく jsp:useBean タグを変換した Java のソースコードの一部です。 synchronized プロックは、 ・ pageContext に保存したオプジェクトを取得する ・ pageContext にオプジェクトを保存する という処理が同一アプリケーションにおいて排他的に実行 されることをイ正します。 もし、この部分の処理が排他的に実行されなかった場 合に何カ起きるのカ甘隹測してみましよう。たとえは、 JSP ページへの初めてのアクセスが同時に発生したとします。 UNIX MAGAZINE 2002.5

9. UNIX MAGAZINE 2002年5月号

連載 JavaServer Pages—O 図 7 同時アクセスがするとアクセス数の里を誤る ① 1 人目のアクセスカウンタ値 readCounter() count 十十 saveCou nter() カウンタ値 ② 2 人目のアクセス -1- CV 1 -1 ・ワ」 CV readCounter() count 十十 ー saveCounter() 2 2 図 8 排他里を追加した Counter2 クラスの getValue() public int getVa1ue ( ) int count このとき、 2 人目のアクセスによる処理が readC 。 unt ー er() を実行し終えたとします。 1 人目のアクセスによるカ ウンタ値はまだアクセスカウンタのファイルに保存されて いないので、 2 人目がアクセスしたときも readCounter() カ芍区す値は、、 1 " です。したがって、、、 count 十十 " を実行 したあとの 2 人目のカウンタ値も 2 です。 このように、 getVaIue() か 1 司時に実行されると、タイ ミングによっては複数の人に同じアクセスカウンタ値を表 示してしまいます。 さらに、 1 人目がアクセス数をファイルに保存するとき には正しく、、 2 " 呆存されますが、 2 人目はもともと正し いアクセス数を取得できていないので、ファイルにも誤っ は、 synchronized のプロックに入るときに、 object が た値である、、 2 " を保存します。 ロックされていないかどうかを卩十ヾ、 このように、図 5 のコードでは、同時アクセスが発生し ・ロックされていなければ、ロックして、、排他的に実行 たときにアクセス数をカウントしそこねる可能生がありま されるコード " を実行 す ( 図 7 ) 。 ・ロックされていればロックカ埆早除されるまで待つ synchronized というように重川します。 この不具合を解決するためには、 1 人目のアクセスカワ これを利用して、 getVaIue() メソッドを書き換えてみ ァイルからアクセス数を読み出してふたたびファイルに保 ましよう。図 8 は、アクセス数を読み込む readCount- 存するまで、 2 人目のアクセスがファイルからアクセス数 er() から、保存する saveCounter() の呼出しまでを排他 を読み出さないようにする必要があります。 的に処理するように書き換えたコードです。 ーー級にこのような処理 ( 里と呼ばさまざまな synchronized でロックするオプジェクトは、 1 人目の 手法があります。 Java ではオプジェクトをロックして排 アクセスでも 2 人目のアクセスでも、同一のものが参照さ 他処理を寒見する方法を言言」として提供しています。 れるオプジェクトであればなんでもかまいません。ここで は、、、 this " オプジェクト、すなわち jsp:useBean で生成 synchronized ( 0 り ec の { した ac オプジェクトを使いました。 排他的に実行されるコード ただし、 ac オプジェクトが page スコープなどの叩ー synchronized (this) { if ( (count=readCounter() ) くの { count 十十 ; saveCounter (count) ; return count ; 125 UNIX MAGAZINE 2002.5