StrutsではWebアプリ開発時によくある問題として、「2度押し」を防ぐメソッドが用意されています。 「2度押し」は、例えばショッピングサイトで注文決定ボタンを押して、画面が切り替わる前に、もう1度注文決定を押ような場合ですね。

・org.apache.struts.Action#saveToken(HttpRequest request)
同期Tokenを保存する
・org.apache.struts.Action#isTokenValid(HttpRequest request,boolean)
同期Tokenを検証する


注文決定ボタンに対応するActionをOrderDesideAction、注文確定(保存)ボタンに対応するActionをOrderAcceptActionとします。この場合、以下のようなコーディングを行います。
?OrderDesideActionのexecute()にsaveTokenを記述。これによって同期Tokenが保存される。

※保存された同期Tokenはhtml:form のtaglibをレンダリングする際に自動的にhidden フィールドとしてフォームに挿入されます。。確認したい場合は、JSPのスクリプトレットに以下の記述をするとTokenを直に見ることが出来ます。
session.getAttribute(org.apache.struts.action.Action.TRANSACTION_TOKEN_KEY)
*同期Tokenはシステム時間(HEXかな?)を元に生成されるようです。

?OrderAcceptActionのexecute()にisTokenValidを記述。Returnがboolean==falseの場合、エラー処理。

ただこの方法には結構大きな1つの問題があります。
もうお分かりかと思いますが、2度押しの1回目は、isTokenValidの戻り値は必ずtrueの為、処理が継続されます。従って、エラー処理のメッセージに困るわけです。更に言うと処理結果の表示にも困りますね。

ただこれで2度押しの危険は避けられます。今回は2度押しはJavaScriptで排除し、isTokenValidはURLの直接指定(例:ブラウザのお気に入りからいきなり注文されたり)による処理排除に使用しました。

何かGoodな解決策を知っている方は是非是非私まで。
新人君との会話で思ったこと。

PreparedStatementインターフェースは、よくStatementインターフェースと比較され、繰り返し処理に強いと言われる。
PreparedStatementは、そのインスタンスの生成時に、あらかじめデータベースで実行されるべきSQL文が与えられ、渡されたSQL文は、データベースで直接即実行が可能だからというのが理由にある。

ただし、そんなに沢山のSQLを繰り返すWebアプリケーション等あまりない。例えば1回のSQLを発行して、入力データをINSERTする程度のもので、その後のConnectionはclose処理されるのが常でもある。

その時に直接のメリットとして考えうるのは以下の点だと思う。

?オブジェクトの生成コスト
何でもnewすればいいというのが、Java習いたての人の常道だが、newはその分、インスタンス分のメモリ領域を確保し割り当てるという、非常に重い処理をしている事を忘れがちである。

?通信コスト
SQLを発行する際に、DB側に毎回送信する必要がない。APサーバーのキャッシュを使用するためだ。

?解析コスト
プリコンパイルされたSQLを毎回発行するのと、コンパイル後に発行されるのでは、解析が既に行われているという点で大きく異なる。

?はAPサーバのCPU使用率、?はDBサーバのCPU使用率、?は両方を削減することが可能で、結果として性能向上が可能になると推測される。
実際APサーバをnmon analizerでトラッキングした所、一部分の重い処理をPreparedStatementにリファクタリングしただけで、約27%のスループット向上が見られた。

小さな積み重ねは大きな一歩に繋がるのだと学んだ。
敬愛する結城先生が困ったさんにヒントをくれた。

Thread-Specific Strage
http://www.hyuki.com/dp/dpinfo_ThreadSpecificStorage.html

java.lang.ThreadLocalは、現在のスレッドに固有な領域(threadに対してspecificな領域)を確保するクラス。という事は、例えばJ2EEアプリケーションにおいてRequest単位のThreadで、固有オブジェクトを参照しつつ処理が行えるという事。

java.spl.Connection等DataSourceを使うとプーリングされて共用されてしまうようなオブジェクトの場合、これをnewしてオブジェクトをセットすれば、とりあえず競合は避けられそう。

-----------------------------------------------------------
後日談

スーパーロボットKさんにこの話をすると

「それはWebsphere 4.0から実装されているねー」

と言われた。Middlewareの既保有機能を作りこんでしまった俺って・・・。
でも格別問題はないし、WASとアプリケーションに2重フォローなんだから、Over Specっぽいけど問題はないでしょう、等と言われてみたり。Middlewareの知識のなさを痛感(だってマニュアル多すぎなんだもん)。早速Redbookを借りてきて勉強してみた。

日々是進歩の糧

お気に入り日記の更新

この日記について

日記内を検索