WEB開発で必ずついて回るのが、Submitボタン二度押しや戻るボタンを押されるなど、勝手な画面遷移をされないような配慮です。Strutsでは同期トークンという機能でこれらの考慮をサポートしてくれます。 実際にサンプルで、ある画面でSubmitを二度押ししたとき、それを検知して二つ目のリクエストをエラーではじくという事を考えてみます。 同期トークンとは †同期トークンの機能とは以下の通りです。
この中で、トークンの生成、トークンチェック、hiddenにトークンを書き出す、などはStrutsが自動でやってくれますので、使う側はトークンをチェックするメソッドをアクションクラスに記述したり、エラー処理だけをやっておけばよいと言うことですね。ラクチンです。 やってみる †流れ †index.do -> IndexAction -> index.jsp -> double.do -> DoubleAction -> success.jsp という流れのサンプルです。 ソース †
セッションにトークンをセット †IndexAction?でSessionにトークンをセットしています。トークンを生成してSessionにセットするメソッドは org.apache.struts.action.Action#saveToken JSPのhiddenにトークンをセット †index.jspではformを使ってSubmitしていますが、出力されるhtmlには自動的にhiddenタグが挿入されます。具体的にはSubmitのformは <html:form method="post" action="/double" > <html:submit /> </html:form> としているだけなのですが出力されるhtmlは <form id="hogeForm" method="post" action="/strutsExamples/double.do"> <div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="612326e14b3ce599284543e2246f170b" /></div> <input type="submit" value="Submit" /> </form> となります。あるキー値でhiddenにトークンがセットされています*3。 次のリクエストで、サーバでトークンのチェック †さてこれでsessionにトークンがセットされ、さらにhtmlのhiddenにトークンがセットされました。次のリクエストを受けるアクション(DoubleAction?)では synchronized (session) { tokenValid = isTokenValid(request); saveToken(request); } if (!tokenValid) { StringBuffer buffer = new StringBuffer(); buffer.append("tokenチェックエラー"); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( new String(buffer), false)); saveErrors(request, errors); } となっています。 isTokenValid(request); がSessionのトークンとhiddenのトークンをチェックするメソッドです。で、次の saveToken(request); で再度トークンを書き換えています。 isTokenValid?(request)はスレッドセーフですが、トークンを変更するまでスレッドセーフでなくてはいけないので、sessionインスタンスのモニタを取得して処理しています*4。 Formでなく<html:link />の場合 †上の例のように<html:form />タグの場合は自動でhiddenタグが挿入されトークンがPostされましたが、<html:link />タグなどの場合は <html:link action="/double" transaction="true">リンク</html:link> としてtransaction属性をtrueに指定します。transaction属性を指定すると http://localhost:8080/strutsExamples/double.do ?org.apache.struts.taglib.html.TOKEN=f8e8901ab4cc126a148fe3d46d5596e7 とパラメタにトークンが設定されます。ちなみにこのtransaction属性はデフォルトはfalseなので、トークンを送信したい場合は明示的に指定してあげる必要があります。 サンプル。 †この記事は
現在のアクセス:124056 |