`

《研磨struts2》第十七章 防止重复提交 之 17.2 使用标签

 
阅读更多


17.2  
使用<s:token/>标签

17.2.1  使用<s:token/>标签入门

Token也被称做令牌,所以使用<s:token/>标签防止重复提交,也常被称做使用令牌防止重复提交。

1:修改页面

       <s:token/>标签的使用非常简单,只需要在提交页面的<s:form>标签内加上子标签<s:token/>就可以了。

如果把提交页面当做重复提交时返回的结果页面的话,通常还需要在这个页面上引用重复提交时的错误信息。重复提交的错误信息以动作错误信息的方式存在,所以我们只要用<s:actionerror/>标签来引用即可。示例代码如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  
  2.     pageEncoding="gb2312"%>  
  3. <html>  
  4. <head>  
  5. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  6. <title>Insert title here</title>  
  7. </head>  
  8. <body>  
  9. <%@ taglib prefix="s" uri="/struts-tags"%>  
  10. <s:actionerror/>  
  11. <hr>  
  12. <s:form action="/tokenAction.action" method="post">  
  13.     <s:token/>  
  14.     <s:textfield name="productId" label="预定的产品编号"/>  
  15.     <s:textfield name="orderNum" label="预定的数量"/>  
  16.     <s:submit value="提交"/>  
  17. </s:form>  
  18. </body>  
  19. </html>  

2:修改struts.xml

使用<s:token/>标签,必须为Action引用名为token的预定义拦截器,它并不在defaultStack拦截器栈里,所以需要手动的引用token拦截器。

如果有重复提交的行为,Struts2将跳转到这个Action定义的名为invalid.token的Result,因此,需要修改struts.xml,示例代码如下:

 

java代码:
  1. <package name="helloworld" extends="struts-default">  
  2.     <action name="tokenAction" class="cn.javass.token.TokenAction">  
  3.         <interceptor-ref name="token"/>  
  4.         <interceptor-ref name="defaultStack"/>  
  5.         <result>/token/list.jsp</result>  
  6.         <result name="invalid.token">/token/add.jsp</result>  
  7.     </action>  
  8. </package>  

我们并没有修改TokenAction。那么,现在再次访问订单提交页面,且再次两次提交,可以看到页面跳转到invalid.token指定的Result,其实就是原来的提交页面,并输出重复提交的提示信息,如图所示:

图17.1 页面被重定向到指定的invalid.token结果

再看看控制台的输出,应该只有一次输出了,示例如下:

 

java代码:
  1. 预定的产品编号是:1,预定数量为:2  
  2. 处理完成!  

可以看到,重复的订单数据只被处理了一次,已经正确的处理了重复提交的问题。但是,还有一个小小的遗憾:页面停到了第二次提交被重定向到invalid.token结果上,而不能正确的走到第一次提交的success结果上。

17.2.2 <s:token/>的原理

为什么简简单单的引用<s:token/>标签,就能够实现防止重复提交的功能呢?

       下面来探究一下<s:token/>的运行原理,对于<s:token/>标签和token拦截器的两部分作用要分开来看:

  • <s:token/>标签在页面初始化的时候,向session中写入了一个名为struts.token的属性,其值是一个随机数;然后在表单中生成了两个隐藏域:struts.token.name域用来记录session中写入属性的名字,struts.token域记录了session的struts.token值一模一样的随机数。
  • token拦截器在请求提交的时候,在Action运行之前,比较session的struts.token属性和表单的struts.token隐藏域的值,如果这两个值相等,则移除session的struts.token属性,然后执行execute方法;如果不相等,则重定向到名为invalid.token的结果。

来把上面的两件事情画成流程图,估计比枯燥的文字更容易让人理解。如下图所示:

图16.2 使用令牌防止重复提交流程图

也许,有些朋友会说,既然struts.token隐藏域记录的值和session的struts.token属性记录的值一模一样,那么,在token拦截器运行的时候,比较的结果还可能不相等吗?

当然是可能的,因为token拦截器的作用在重复提交的时候才能显现出来。一起来分析分析,按照运行顺序,先后发生了如下的几件事情:

  • 首先,用户访问页面,这时候,<s:token/>标签要向session写入struts.token属性,假设这个随机数为123456789。那么,<s:token/>标签也同时要向<s:form/>写入名为struts.token的隐藏域,它的值也是123456789。
  • 然后,用户第一次提交这个页面,这时候,session中的struts.token属性和表单中的struts.token隐藏域的值都为123456789,判断为相等,所以token拦截器移除了session中的struts.token这个属性,整个防止重复提交的关键就在这步,然后继续运行execute方法,所以,这次提交是有效的。
  • 在第一次请求还没有运行完,用户再一次提交了这个页面。这时候,session中已经没有了struts.token属性,已经在第一次请求时被token拦截器移除了,但是表单中仍有struts.token隐藏域,所以二者肯定不相等了,那么,这次请求就被认为是重复请求,重定向到invalid.token指定的Result。

       补充说明:如果指定了<s:token/>标签的name属性,那么对session写入的属性名就不再是默认的struts.token,而是这个name值;同理对表单写入的隐藏域名也不再是默认的struts.token,也是这个name值了。在理解<s:token/>标签和token拦截器的作用时,基本不用理会struts.token.name隐藏域的作用。

 

私塾在线网站原创《研磨struts2》系列

转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4150.html

欢迎访问http://sishuok.com获取更多内容

4
5
分享到:
评论
2 楼 markhai_85 2012-07-26  
我理解错了,重复提交后,add.jsp不应该刷新
1 楼 markhai_85 2012-07-26  
s:token
还有个大缺陷,用户第三次点击提交时,就没法拦截了!

相关推荐

    研磨Struts2

    ### 知识点十三:防止重复提交 #### 13.1 问题背景 在Web应用中,由于网络延迟等原因,用户可能会不小心多次点击提交按钮,导致数据重复提交。 #### 13.2 解决方案 - **Token机制**:每次提交前生成一个唯一的...

    研磨Struts2配书视频对应的演示源代码

    这个压缩包中的“研磨Struts2配书视频对应的演示源代码”是《研磨Struts2》一书作者为了帮助读者更好地理解和实践书中理论知识而提供的实际示例代码。 首先,让我们深入理解Struts2的核心概念和技术特性: 1. **...

    研磨struts2 高清版

    由于文件较大,我把这个文档切割为2部分,这是第一部分,请下载完第一部分后一定要下载第二部分,否则不能阅读。

    《研磨Struts 2》PDF版本下载.txt

    根据提供的文件信息,我们可以推断出这是一份关于《研磨Struts 2》书籍PDF版本的下载资源。为了更好地理解和概括这份资料所涉及的知识点,我们先来了解一下Struts 2框架及其重要性,然后深入探讨《研磨Struts 2》这...

    研磨Struts2配书视频对应的PPT

    《研磨Struts2》这本书是专门针对Struts2框架的学习指南,通过深入浅出的方式讲解了Struts2的核心概念和技术。其配套的PPT和视频旨在帮助读者更直观地理解书中的理论知识,并将其付诸实践。 在研读《研磨Struts2》...

    研磨Struts2 高清完整版.part2

    研磨Struts2 高清完整版,请和第一部分一起下载啊

    研磨Struts2_12859679_高清完整版.part2.rar

    研磨Struts2_12859679_高清完整版

    研磨struts

    《研磨Struts2》这本书主要介绍了Struts2的基础知识、实践应用以及其核心概念。 1. **MVC模式**:MVC是一种设计模式,用于分离应用程序的业务逻辑、数据和用户界面。在Struts2中,Action类代表Controller,负责处理...

    研磨Struts2-高清-完整目录-2011年10月

    研磨Struts2-高清-完整目录-2011年10月,分享给所有需要的人

    研磨设计模式(完整带书签).part2.pdf

    第17章 策略模式(Strategy) 第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式...

    研磨设计模式-part2

    第17章 策略模式(Strategy) 第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式...

    研磨设计模式(完整带书签).part1.pdf

    第17章 策略模式(Strategy) 第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式...

    研磨设计模式.part2(共4个)

    第17章 策略模式(Strategy) 第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式...

    研磨设计模式.part2

    研磨设计模式.part2 一定要下载5部分

Global site tag (gtag.js) - Google Analytics