談網站優化要點

 前幾天進行了對現時平臺(基於struts2)的一些細節改進思考,總結了一些方法和技巧,貼出來共享一下吧。

防止表單重複提交

問題描述:用戶提交表單時可能因爲網速的原因,或者網頁被惡意刷新,致使同一條記錄重複插入到數據庫中,這是一個比較棘手的問題。我們可以從客戶端和服務器端一起着手,設法避免同一表單的重複提交。

  解決方案:

 1.使用客戶端腳本
提到客戶端腳本,經常使用的是JavaScript進行常規輸入驗證。在下面的例子中,我們使用它處理表單的重複提交問題,請看下面的代碼:

   

<form method="post" name="register" action="test.php" enctype=
"multipart/form-data">
<input name="text" type="text" id="text" />
<input name="cont" value="
提交" type="button" onClick="document.
register.cont.value='
正在提交,請等待...';document.register.cont.
disabled=true;document.the_form.submit();">
</form>

 上述方法,主要是將按鈕的提交狀態改變爲disabled

2.利用Struts2的令牌機制。

防止表單重複提交主要用的到標籤是<s: token />,攔截器 <interceptor-ref name="token" />,還有一個默認的返回值<result name="invalid.token">/input.jsp</result>

在頁面加載時,<s: token />產生一個GUIDGlobally Unique Identifier,全局唯一標識符)值的隱藏輸入框如:

<input type="hidden" name="struts.token.name" value="struts.token"/>
<input type="hidden" name="struts.token" value="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR"/>

同時,將GUID放到會話(session)中;在執行action之前,“token”攔截器將會話token與請求token比較,如果兩者相同,則將會話中的token刪除並往下執行,否則向actionErrors加入錯誤信息。如此一來,如果用戶通過某種手段提交了兩次相同的請求,兩個token就會不同。

下面用零配置來演示 token的作用

/WEB-INF/content/test-success.jsp

<%@ page  contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags"  %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>

</head>

 

    <body>

       <s:actionerror/>

       <s:form action="test!save.action" method="POST">

           <s:textfield name="message" label="請輸入您的信息"/>

           <s:token name="token"/>

           <s:submit value="確定" />

       </s:form>

    </body>

</html>

/WEB-INF/content/error.jsp

<%@ page  contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags"  %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

  <html>

  <body>

  <s:actionerror/>

    不能重複提交表單!

  </body>

</html>

/WEB-INF/content/test-ok.jsp

<%@ page  contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags"  %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

    <body>

       SAVE OK!

    </body>

</html>

TestAction.java

package com.fun.actions;

 

import org.apache.struts2.convention.annotation.InterceptorRef;

import org.apache.struts2.convention.annotation.Result;

import org.apache.struts2.convention.annotation.Results;

 

import com.opensymphony.xwork2.ActionSupport;

@Results({

@Result(name="invalid.token",location="/index.html",type="redirect")})

@InterceptorRefs({@InterceptorRef(value="token",params={"includeMethods","save"}),@InterceptorRef("defaultStack")  })

public class TestAction extends ActionSupport {

    private String message;

    public String execute(){

    return SUCCESS;

    }

   

 

 

    public String save(){

    return "ok";

    }

    public String getMessage() {

       return message;

    }

    public void setMessage(String message) {

       this.message = message;

    }

   

}

 其實,最主要的就是 token攔截器中還有 includeMethods()這個方法,表示的是,Action中的哪個方法需要經過攔截器。屬性excludeMethods()這個方法表示的是哪個方法不經過攔截器。如果,沒有加上“defaultStack”這個攔截器的話,則ActionContext的值將爲null

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章