06Action中的Struts廣告

 

Struts令牌防止重複提交html

 

在Action中的add方法中,咱們須要將Token值明確的要求保存在頁面中,只需增長一條語句:saveToken(request);,以下所示:
  
  public ActionForward add(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  //前面的處理省略
  
  saveToken(request);
  
  return mapping.findForward("add");
  
  }在Action的insert方法中,咱們根據表單中的Token值與服務器端的Token值比較,以下所示:
  
  public ActionForward insert(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  if (isTokenValid(request, true)) {
  
  // 表單不是重複提交
  
  //這裏是保存數據的代碼
  
  } else {
  
  //表單重複提交
  
  saveToken(request);
  
  //其它的處理代碼
  
  }
  
  }
  
  其實使用起來很簡單,舉個最簡單、最須要使用這個的例子:
  
  通常控制重複提交主要是用在對數據庫操做的控制上,好比插入、更新、刪除等,因爲更新、刪除通常都是經過id來操做(例如:updateXXXById, removeXXXById),因此這類操做控制的意義不是很大(不排除個別現象),重複提交的控制也就主要是在插入時的控制了。
  
  先說一下,咱們目前所作項目的狀況:
  
  目前的項目是用Struts+Spring+Ibatis,頁面用jstl,Struts複雜View層,Spring在Service層提供事務控制,Ibatis是用來代替JDBC,全部頁面的訪問都不是直接訪問jsp,而是訪問Structs的Action,再由Action來Forward到一個Jsp,全部針對數據庫的操做,好比取數據或修改數據,都是在Action裏面完成,全部的Action通常都繼承BaseDispatchAction,這個是本身創建的類,目的是爲全部的Action作一些統一的控制,在Struts層,對於一個功能,咱們通常分爲兩個Action,一個Action裏的功能是不須要調用Struts的驗證功能的(常見的方法名稱有add,edit,remove,view,list),另外一個是須要調用Struts的驗證功能的(常見的方法名稱有insert,update)。
  
  就拿論壇發貼來講吧,論壇發貼首先須要跳轉到一個頁面,你能夠填寫帖子的主題和內容,填寫完後,單擊「提交」,貼子就發表了,因此這裏通過兩個步驟:
  
  一、轉到一個新增的頁面,在Action裏咱們通常稱爲add,例如:
  
  public ActionForward add(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  throws Exception {
  
  //這一句是輸出調試信息,表示代碼執行到這一段了
  
  log.debug(":: action - subject add");
  
  //your code here
  
  //這裏保存Token值
  
  saveToken(request);
  
  //跳轉到add頁面,在Structs-config.xml裏面定義,例如,跳轉到subjectAdd.jsp
  
  return mapping.findForward("add");
  
  }
  
  二、在填寫標題和內容後,選擇 提交 ,會提交到insert方法,在insert方法裏判斷,是否重複提交了。
  
  public ActionForward insert(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response){
  
  if (isTokenValid(request, true)) {
  
  // 表單不是重複提交
  
  //這裏是保存數據的代碼
  
  } else {
  
  //表單重複提交
  
  saveToken(request);
  
  //其它的處理代碼
  
  }
  
  }
  
  下面更詳細一點(注意,下面全部的代碼使用全角括號):
  
  一、你想發貼時,點擊「我要發貼」連接的代碼能夠裏這樣的:
  
  〈html:link action="subject.do?method=add"〉我要發貼〈/html:link〉
  
  subject.do 和 method 這些在struct-config.xml如何定義我就不說了,點擊連接後,會執行subject.do的add方法,代碼如上面說的,跳轉到subjectAdd.jsp頁面。頁面的代碼大概以下:
  
  〈html:form action="subjectForm.do?method=insert"〉
  
  〈html:text property="title" /〉
  
  〈html:textarea property="content" /〉
  
  〈html:submit property="發表" /〉
  
  〈html:reset property="重填" /〉
  
  〈html:form〉
  
  若是你在add方法里加了「saveToken(request);」這一句,那在subjectAdd.jsp生成的頁面上,會多一個隱藏字段,相似於這樣〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,
  
  二、點擊發表後,表單提交到subjectForm.do裏的insert方法後,你在insert方法裏要將表單的數據插入到數據庫中,若是沒有進行重複提交的控制,那麼每點擊一次瀏覽器的刷新按鈕,都會在數據庫中插入一條相同的記錄,增長下面的代碼,你就能夠控制用戶的重複提交了。
  
  if (isTokenValid(request, true)) {
  
  // 表單不是重複提交
  
  //這裏是保存數據的代碼
  
  } else {
  
  //表單重複提交
  
  saveToken(request);
  
  //其它的處理代碼
  
  }
  
  注意,你必須在add方法裏使用了saveToken(request),你才能在insert裏判斷,不然,你每次保存操做都是重複提交。
  
  記住一點,Struts在你每次訪問Action的時候,都會產生一個令牌,保存在你的Session裏面,若是你在Action裏的函數裏面,使用了saveToken(request);,那麼這個令牌也會保存在這個Action所Forward到的jsp所生成的靜態頁面裏。
  
  若是你在你Action的方法裏使用了isTokenValid,那麼Struts會將你從你的request裏面去獲取這個令牌值,而後和Session裏的令牌值作比較,若是二者相等,就不是重複提交,若是不相等,就是重複提交了。
  
  因爲咱們項目的全部Action都是繼承自BaseDispatchAction這個類,因此咱們基本上都是在這個類裏面作了表單重複提交的控制,默認是控制add方法和insert方法,若是須要控制其它的方法,就本身手動寫上面這些代碼,不然是不須要手寫的,控制的代碼以下:
  
  public abstract class BaseDispatchAction extends BaseAction {
  
  protected ActionForward perform(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  throws Exception {
  
  String parameter = mapping.getParameter();
  
  String name = request.getParameter(parameter);
  
  if (null == name) { //若是沒有指定 method ,則默認爲 list
  
  name = "list";
  
  }
  
  if ("add".equals(name)) {
  
  if ("add".equals(name)) {
  
  saveToken(request);
  
  }
  
  } else if ("insert".equals(name)) {
  
  if (!isTokenValid(request, true)) {
  
  resetToken(request);
  
  saveError(request, new ActionMessage("error.repeatSubmit"));
  
  log.error("重複提交!");
  
  return mapping.findForward("error");
  
  }
  
  }
  
  return dispatchMethod2(mapping, form, request, response, name);
  
  }
  
  }數據庫

 

當年揚子老校區   合同的加薪階段爲世界盃而著文咬文嚼字中國節apache

相關文章
相關標籤/搜索