WEB開発で必ずついて回るのが、Submitボタン二度押しや戻るボタンを押されるなど、勝手な画面遷移をされないような配慮です。Strutsでは同期トークンという機能でこれらの考慮をサポートしてくれます。
実際にサンプルで、ある画面でSubmitを二度押ししたとき、それを検知して二つ目のリクエストをエラーではじくという事を考えてみます。
同期トークンの機能とは以下の通りです。
この中で、トークンの生成、トークンチェック、hiddenにトークンを書き出す、などはStrutsが自動でやってくれますので、使う側はトークンをチェックするメソッドをアクションクラスに記述したり、エラー処理だけをやっておけばよいと言うことですね。ラクチンです。
index.do -> IndexAction -> index.jsp -> double.do -> DoubleAction -> success.jsp
という流れのサンプルです。
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
saveToken(request);
return mapping.findForward("success");
}<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <%@ page language="java" contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@page import="org.apache.struts.Globals"%> <html:html xhtml="true" lang="true"> <head> <title>同期トークンの稼動確認JSP</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> <html:base /> </head> <body> <html:form method="post" action="/double" > <html:submit /> </html:form> <%=session.getAttribute(Globals.TRANSACTION_TOKEN_KEY) %> </body> </html:html>
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ActionMessages errors = new ActionMessages();
HttpSession session = request.getSession();
boolean tokenValid = false;
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);
}
}IndexActionでSessionにトークンをセットしています。トークンを生成してSessionにセットするメソッドは
org.apache.struts.action.Action#saveToken
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。
上の例のように<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なので、トークンを送信したい場合は明示的に指定してあげる必要があります。
この記事は
現在のアクセス:126036