|
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なので、トークンを送信したい場合は明示的に指定してあげる必要があります。 サンプル。 †この記事は
現在のアクセス:125466 |