J2EE框架-重复提交、重复刷新、防止后退的问题以及处理方式_第1页
J2EE框架-重复提交、重复刷新、防止后退的问题以及处理方式_第2页
J2EE框架-重复提交、重复刷新、防止后退的问题以及处理方式_第3页
J2EE框架-重复提交、重复刷新、防止后退的问题以及处理方式_第4页
J2EE框架-重复提交、重复刷新、防止后退的问题以及处理方式_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、重复提交、重复刷新、防止后退的问题以及处理方式二零零六年十二月目 录第一章 问题场景 3 重复提交、重复刷新的场景 3 防止后退的场景 3第二章 如何处理 4 客户端处理 4 重复刷新、重复提交 4 防止后退 5 服务器端处理(这里说STRUTS框架的处理) 5 使用方法 5 基本原理 6 以上例子的代码分析 6 总结 10第一章 问题场景先了解为什么要处理这样的问题?或者专业一点就是它适合的场景是什么? 一.1 重复提交、重复刷新的场景重复提交、重复刷新都是来解决系统重复记录的问题。也就是说某个人在多次的提交某条记录。(为什么?也许是闲了没有事情干的;最有可能是用户根本就不知道自己的提交结果

2、是否已经执行了?)但出现了这样的问题并不见得就必须处理,要看你所开发的系统的类别而定。比如你接手的是某个资源管理系统,系统本身从需求的角度根本就不允许出现"重复"的记录,在这样需求的约束条件下,去执行重复的提交动作只会引发“业务级异常”的产生,根本就不可能执行成功。一.2 防止后退的场景"防止后退"操作的原因是什么?比如你在开发某个投票系统,它有很多的步骤,并且这些步骤之间是有联系的,比如第一步会将某些信息发送给第二步,第二步缓存了这些信息,同时将自身的信息发送给了第三步等等,如果此时用户处在第三步骤下,我们想象一下某个淘气用户的用户点击了后退按钮,此时

3、屏幕出现了第二步骤的页面,他再次的修改或者再次的提交,进入到下一个步骤(也就是第三步骤),错误就会在此产生?什么错误呢?最为典型的就是这样的操作直接导致了对于第一个步骤信息的丢失!(如果这样的信息是依靠Request存放的话,当然你可以存放在Session或者更大的上下文环境中,但这不是个好主意!)第二章 如何处理处理的方式分是客户端和服务器端两种。二.1 客户端处理二.1.1 重复刷新、重复提交方法一:设置一个变量,只允许提交一次。方法二:将提交按钮或者image置为disableonsubmit="document.getElementById(submitInput.disab

4、led = true; return true;" > 二.1.2 防止后退方法一:更改浏览器的历史纪录使用window.history.forward(方法,调用window.history.forward(方法即可。二.2 服务器端处理(这里说Struts框架的处理)利用同步令牌(Token)机制来解决Web应用中重复提交的问题,Struts也给出了一个参考实现。二.2.1 使用方法1、假如你要提交的页面为toSubmit.jsp。2、在打开toSubmit.jsp的Action1中加入:saveToken(request,例如:public ActionForward e

5、xecute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response throws Exception /生成同步令牌saveToken(request; return mapping.findForward("toSubmit"3、在提交toSubmit.jsp的Action2中加入:isTokenValid(request, true,例如:public ActionForward execute(ActionMapping mappin

6、g,ActionForm form, HttpServletRequest request,HttpServletResponse response throws Exception / 验证同步令牌if (isTokenValid(request, true /未重复提交,做未重复提交做的事情System.out.println("执行提交操作"else /重复提交,做重复提交做的事情System.out.println("重复提交" return mapping.findForward("Error"4、使用注意:toSubmit

7、.jsp中的form使用struts的标签 。如不使用struts的标签 。那在toSubmit.jsp的form中应该加上如下代码:<%String tokenStr = (String request.getSession(.getAttribute(Globals.TRANSACTION_TOKEN_KEY;%>同时也应该导入Globals类<% page import="org.apache.struts.Globals"%>二.2.2 基本原理服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否

8、匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。二.2.3 以上例子的代码分析1、在session中放入同步令牌在Action1中加入saveToken(request方法,其实是调用TokenProcessor类的saveToken方法如下:public synchronized void saveToken(HttpServletRequest request HttpSessio

9、n session = request.getSession(;String token = generateToken(request;if (token != null session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token;Struts根据用户会话ID和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现是TokenProcessor类中的generateToken(方法。protected String generateToken(HttpServletRequest request HttpSession sessio

10、n = request.getSession(; try byte id = session.getId(.getBytes(; byte now = new Long(System.currentTimeMillis(.toString(.getBytes(; MessageDigest md = MessageDigest.getInstance('MD5' md.update(id; md.update(now; return (toHex(md.digest(; catch (IllegalStateException e return (null; catch (No

11、SuchAlgorithmException e return (null; 很明显是在session中放入了同步令牌,名称为Globals.TRANSACTION_TOKEN_KEY。2、在页面创建hidden元素这个类的doStartTag(方法会调用renderToken(方法:protected String renderToken( StringBuffer results = new StringBuffer(;HttpSession session = pageContext.getSession(;if (session != null String token =(Strin

12、g session.getAttribute(Globals.TRANSACTION_TOKEN_KEY;if (token != null results.append("results.append(Constants.TOKEN_KEY;results.append("" value=""results.append(token;if (this.isXhtml( results.append("" />" else results.append("">"return

13、 results.toString(;其意为:当检测到session中的Globals.TRANSACTION_TOKEN_KEY不为空时,在toSubmit.jsp页面创建元素:名称为:org.apache.struts.taglib.html.TOKEN也就是Globals.TRANSACTION_TOKEN_KEY;值为:session中的Globals.TRANSACTION_TOKEN_KEY的值,即为同步令牌值。所以:如不使用struts的标签 ,那页面的form中的org.apache.struts.taglib.html.TOKEN需要自己创建。第三步、验证同步令牌在Actio

14、n2中加入isTokenValid方法,实际上是调用TokenProcessor类的isTokenValid方法如下:public synchronized boolean isTokenValid(HttpServletRequest request, boolean reset / Retrieve the current session for this requestHttpSession session = request.getSession(false;if (session = null return false;/ Retrieve the transaction token

15、 from this session, and/ reset it if requestedString saved = (String session.getAttribute(Globals.TRANSACTION_TOKEN_KEY;if (saved = null return false;if (reset this.resetToken(request;/ Retrieve the transaction token included in this requestString token = request.getParameter(Constants.TOKEN_KEY;if (token = null return false;return saved.equals(token;它首先取得session中的令牌值,然后resetToken,再从页面hidden元素取来令牌值,进行比较,如果相等则为第一次提交,不等则为重复提交。其中resetToken方法如下:public synchronized void resetToken(HttpS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论