struts 1.xフォームの重複コミットの問題の解決
6337 ワード
フォームの記入が完了するたびに「発行」をクリックすると、strutsでactionが関連するビジネスロジックを実行し、forwardオブジェクトを介してページに移動します.このときページをリフレッシュすると、同じ論理が実行されます.たとえば、データベースにデータを記録すると、上記の場合、データベースに同じデータが2つあります.このような状況を回避するために、いくつかの解決策があります:1:ビジネスロジックを実行した後、1つのForwardオブジェクトを返します.このforwardオブジェクトのpath属性はべき乗などのXXX.do操作を構成するべきで、このように解決することができますが、ユーザーの要求に合わない可能性がありますので、他の方法があります.2:リダイレクト、プロファイル内でredirectプロパティを構成し、xxx.jspにリダイレクトします.この場合request範囲内のパラメータが失われ、xxx.jspがこれらのパラメータを要求しなければ、操作したデータがsession範囲内に保存されていれば、全体の効果に影響しません.しかし、やはり弊害がある.3:struts 1.xトークンを使用すると、このような問題をうまく解決できます.必要条件:フォーム内でstrutsのライブラリラベル(次の例を示します.
LoginAction:
login.jspに戻ってソースコードを確認します.
LoginAction:
package com.web.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
public class LoginAction extends DispatchAction {
public ActionForward get(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// ( jsp 32 jsessionid)\
this.saveToken(request);
System.out.println("begin save");
return mapping.findForward("login");
}
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
/**//*if(this.isTokenValid(request))
{
System.out.println("valid");
this.resetToken(request);
return mapping.findForward("ok");
}*/
//
if(this.isTokenValid(request,true))
{
System.out.println("valid");
return mapping.findForward("ok");
}
else
{
System.out.println("invalid");
return mapping.findForward("error");
}
}
}
struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<data-sources />
<form-beans>
<form-bean name="loginForm" type="com.web.form.LoginForm"></form-bean>
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings>
<action path="/login" parameter="method" name="loginForm"
type="com.web.action.LoginAction">
<forward name="login" path="/login.jsp" />
<forward name="ok" path="/ok.jsp" />
<forward name="error" path="/error.jsp" />
</action>
</action-mappings>
<message-resources parameter="" />
</struts-config>
index.jsp:
<% @page contentType="text/html; charset=GBK"%>
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<html>
<head>
<title>My Jsp</title>
</head>
<body>
<a href="${ctx}/login.do?method=get"> </a>
</body>
</html>
login.jsp:
<% @page contentType="text/html; charset=GBK"%>
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% @taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<html>
<head>
<title>My Jsp</title>
</head>
<body>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<!-- html , token -->
<html:form action="login.do?method=login" method="post">
<html:submit value=" "></html:submit>
</html:form>
</body>
</html>
最初に実行すると、「成功」というメッセージが表示されます.login.jspに戻ってソースコードを確認します.
<html>
<head>
<title>My Jsp</title>
</head>
<body>
<form name="loginForm" method="post" action="/strutsToken/login.do?method=login">
<div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="d7484f95247cf242a6f35107a1c7ac25"></div>
<input type="submit" value=" ">
</form>
</body>
</html>
私たちが書いたlogin.jspと比較すると、32ビットの唯一のJsessionIDを値として生成します.LoginActionのgetメソッドのsaveToken(request)同じです.この文の役割はjsessionidをrequestの範囲に保存することです.私たちが後退して再呼び出します:if(this.isTokenValid(request,true)) { System.out.println("valid"); return mapping.findForward("ok"); } すると、login.jspから送られてきたjsessionidとrequestを比較します.同じであれば、説明は合法ではありません.私たちの操作はすべて要求セッションで操作されているからです.繰り返し提出していることを説明します.異なる場合、説明は唯一のjsessionidを再生成しました(新しいブラウザを開きます)を開き、新しいセッションを開き、再送信するのが合法です.これによりフォームの重複送信の問題が防止されます.フォームの重複送信を防止するために、一般的にactionメソッドを設計する際に、データを入力するなど、2つのメソッド、add()とinsert()を設計し、addメソッドにトークンを保存してページに移動し、ページにinsertメソッドにコミットし、トークンを判断します.