天天看点

Struts2框架学习之七:避免表单重复提交

前言

防止表单重复提交在web开发中是一个经常遇到的问题,一般来避免重复提交有两种方式:客户端javascript代码实现和服务端代码实现。这里主要介绍服务端的实现方式。在服务端实现表单重复提交的基本原理是:通过创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏域随表单一起发送给客户端,同时在session中保存令牌值。在用户提交表单的时候判断提交参数的令牌值与session中的是否相等,如果相等则清除,不再使用这个令牌值,,然后执行后续的处理;如果两者不相等,表示已经提交过表单,服务端产生一个新的令牌值并保存到session中。当用户下次访问的的时候,将新产生的领牌值发送到客户端。

struts2的实现方式

在struts2中通过使用拦截器来实现的,机制与前言中采用令牌的方式是一样的。可以通过两种方式实现避免重复表单(实际上就是两个不同的拦截器):token拦截器和tokensession拦截器。由于在struts-default.xml的默认拦截器栈中并没有将这两个拦截器作为默认实现,所以需要在action中手动添加这两个拦截器。这两种方式的区别在于:使用token拦截器重复提交表单的时候,浏览器会跳转到一个错误页面,而使用更tokensession拦截器重复提交表单的话是不会跳转的,仍然在成功之后页面。需要注意的是,使用者两个拦截器重复提交表单的时候,都只会向服务器提交一次请求,所以这种方式可以有效降低服务器的负担。

具体的例子

在使用以上拦截器进行测试的时候,需要如下步骤:

步骤一:编写login.jsp、success.jsp和error.jsp三个页面

login.jsp

success.jsp

error.jsp

步骤二:编写action

步骤三:配置struts.xml

这里需要提出的是,action中name属性为<code>invalid.token</code>的result是不可少的。

步骤四:发布测试

经过测试,发现使用token拦截器在重复提交表单的时候会转到error.jsp,而使用tokensession拦截器在重复提交表单的时候不会转到error.jsp。

显示等待页面

有时候在action需要处理较长时间的时候,一般是5到10分钟,在这种情况下向用户显示一个等待页面可能会比较友好一些。在struts2中通过使用execandwait拦截器就可以非常轻松实现这点。

execandwait的工作机制:

execandwait拦截器能够让一个a执行时间超过5分钟的action在后台运行,并向用户显示一个等待页面。之所以是5分钟是因为这样防止http请求超时。当一个请求到来的时候,execandwait拦截器会创建一个线程来执行session,然后返回一个等待页面,这样用户就知道请求在处理中。等待页面包含了自动刷新功能,在超时之前,浏览器会向初始请求的action再次发起请求,以便知道后台action是否已经执行完毕。如果action仍然没有执行完毕,则继续显示等待页面,如果action已经执行完毕,则等待页面将发生跳转,向用户处理结束之后的页面。

execandwait拦截器有以下几个参数:

threadpriority:执行线程的优先级

delay:指定在显示等待页面前初始的延迟加载时间,单位是毫秒

delaysleepinternal:指定检查后台线程是否执行完毕的时间间隔,必须和delay参数一起使用,单位是毫秒,默认是100毫秒。表示每100毫秒进行一次检查

使用execandwait拦截器显示等待页面,首先需要编写一个等待页面:

在head 标签中需要添加自动刷新meta标签,不然是不会出发自动检查的。在这个等待页面中,表示3秒后就会跳转到成功页面。

之后是添加execandwait拦截器的配置:

注意到tokenaction类中,使用tread.sleep(3000),表示通过让线程休眠的方式延长action的处理时间,还有一点要注意的是struts.xml中execandwait拦截器的delay参数的值需要小于thread.sleep(time)的时间。这样就能保证在action处理结束之前完成显示等待页面,不然很可能会直接success.jsp页面了。

继续阅读