互联网的长尾理论:Struts2防止表单重复提交

来源:百度文库 编辑:偶看新闻 时间:2024/04/19 08:25:48

Struts2防止表单重复提交

2011-01-13 18:07 151人阅读 评论(0) 收藏 举报

1.    预备知识:

a)      拦截器配置

在struts-default.xml中定义了很多拦截器,这些拦截器就是用来完成许多强劲功能的保证,而且可以根据已定义的若干拦截器中的某几个拦截器构建成interceptor-stack拦截器栈,其实拦截器栈还可以由拦截器栈组成。即从Struts2高层的角度来看,二者没有什么区别。

我们可以在中增加这样一行即表示将该拦截器作为整个包的默认拦截器,它会自动附加到我们的每一个Action中。并且在一个中只能使用定义一个默认的拦截器。

没有引用任何一个拦截器,那么默认的defaultStack会自动附加到

手工引用任何一个拦截器,那么默认的defaultStack就不会附加到

若还想使用默认拦截器,则只能再通过手工方式导入

如果没有引用Struts2的默认拦截器,那么就会影响到整体的输入校验即其它的一些功能

Struts2拦截器的配置和使用都很easy,这得益于其底层的良好架构以及它的AOP的思想

该拦截器即标准的AOP思想,代码不写死到Action里,而是根据配置灵活附加到Action中

使用上,Struts2拦截器并不复杂。但实现上,是很复杂的,其底层用到了动态代理的机制

 

b)      造成重复提交主要的两个原因:

 

1)            一是,服务器处理时间久。当用户在表单中填完信息,点击“提交”按钮后,由于服务器反应时间过长没能及时看到响应信息,或者出于其它目的,再次点击“提交”按钮,从而导致在服务器端接收到两条或多条相同的信息。如果信息需要存储到后台数据库中,如此以来就会产生数据库操作异常提示信息,以至于给用户带来错误信息提示,从而给用户的使用带来不便。

 

2)            二是,forward跳转引起的重复提交。当用户将信息提交到服务器,服务器响应采用forward方式调转到下一个页面后,此时地址栏中显示的是上个页面的URL,若刷新当前页面,浏览器会将再次提交用户先前输入的数据,就会再次出现表单重复提交的问题。当然你可以选择redirect方式跳转页面,这样就不会出现重复提交的问题;但有时为了达到某种效果或式。者出于网站安全的目的需要隐藏网页跳转,而不得不采用forward跳转方

 

c)       token的简单理解:

1)当用户首次访问包含表单的页面时,服务器会在这次会话中创建一个session对象,并产生一个令牌值,然后将这个令牌值作为隐藏输入域的值,随表单一起发送到服务器端,同时将令牌值保存到Session中。

2) 当用户提交页面时,服务器首先判断请求参数中的令牌值和Session中保存的令牌值是否相等,若相等,则清楚Session中的令牌值,然后执行数据处理操作。如果不相等,则提示用户已经提交过了表单,同时产生一个新的令牌值,保存到Session中。当用户重新访问提交数据页面时,将新产生的令牌值作为隐藏输入域的值。

 

 

注意问题:请简述客户端跳转和服务器端跳转之间的区别

客户端跳转时用HttPservletResopse对象的sendRedirect函数实现,服务器端跳转是使用RequestDispather对象的forward方法实现的。这两者之间的区别主要体现在三个方面:

1. 使用服务器端跳转时,客户浏览器的地址栏并不会显示目标地址的URL,而是用客户端跳转时,地址栏当中会显示目标资源的URL;

2. 服务器端跳转是由客户端发送一个请求,请求一个服务器资源——如JSP和Servlet——,这个资源又将请求转到另一个服务器资源,然后再给客户端发送一个响应,也就是说服务器端跳转是客户端发送一次请求,服务器端给出一次响应;而客户端跳转的流程则不同。客户端同样是发送一个请求给服务器端资源,这个服务器资源会首先给客户端一个响应,客户端再根据这个响应当中所包含的地址,再次向服务器端发送一个请求,也就是说客户端跳转是两次请求,两次响应;

3.         在进行客户端跳转和服务器端跳转时,都需要指定目标资源的URL,如果这个路径以“/”开始。在客户端跳转当中“/”代表的是应用服务器根目录,而在服务器端跳转当中代表的是应用程序根目录。 

 

2.开始解决

使用struts2  token拦截器

struts2的拦截器实现了防止表单重复提交的功能,即token拦截器,在表单提交页面写上,在struts.xml配置文件中相应的action上配置拦截器。此拦截器只能用在有form的提交请求上。

Jsp页面部分代码:

 

在表单提交页面写上

"add" method="post">

   

    "userName" label="用户名">

    "password" label="密码">

   

 

 在struts.xml配置文件中相应的action上配置拦截器

"*" class="tutorial.UploadFiles" method="{1}">
"token">

"filesShow">

/filesShow.jsp

 

Struts2的内置拦截器:

 

 

 

 

核心提示:名称 描述 alias 实现在不同请求中相似参数别名的转换。 autowiring 这是个自动装配的拦截器,主要用于当Struts2和Spring整合时,Struts2可以使用自动装配的方式来访问Spring容器中的Bean。 chain 构建一个Action链,使当前Action可以访问前一个Action的属性

名称

描述

 

alias

实现 在不同请求中相似参数别名的转换。

 

autowiring

这是个自动装配的拦截器,主要用于当Struts2和Spring整 合时,Struts2可以使用自动装配的方式来访问Spring容器中的Bean。

 

chain

构建一个Action链,使当 前Action可以访问前一个Action的属性,一般和一起使用。

 

conversionError

这 是一个负责处理类型转换错误的拦截器,它负责将类型转换错误从ActionContext中取出,并转换成Action的FieldError错误。

 

createSession

该 拦截器负责创建一个HttpSession对象,主要用于那些需要有HttpSession对象才能正常工作的拦截器中。

 

debugging

当 使用Struts2的开发模式时,这个拦截器会提供更多的调试信息。

 

execAndWait

后台执行Action,负责将等 待画面发送给用户。

 

exception

这个拦截器负责处理异常,它将异常映射为结果。

 

fileUpload

这 个拦截器主要用于文件上传,它负责解析表单中文件域的内容。

 

i18n

这是支持国际化的拦截器,它负责把所选的语言、区域放入 用户Session中。

 

logger

这是一个负责日志记录的拦截器,主要是输出Action的名字。

 

model-driven

这 是一个用于模型驱动的拦截器,当某个Action类实现了ModelDriven接口时,它负责把getModel()方法的结果堆入 ValueStack中。

 

scoped-model-driven

如果一个Action实现了一个 ScopedModelDriven接口,该拦截器负责从指定生存范围中找出指定的Modol,并将通过setModel方法将该Model传给 Action实例。

 

params

这是最基本的一个拦截器,它负责解析HTTP请求中的参数,并将参数值设置成Action对 应的属性值。

 

prepare

如果action实现了Preparable接口,将会调用该拦截器的prepare()方法。

 

static-params

这 个拦截器负责将xml中标签下标签中的参数传入action。

 

scope

这 是范围转换拦截器,它可以将Action状态信息保存到HttpSession范围,或者保存到ServletContext范围内。

 

servlet-config

如 果某个Action需要直接访问Servlet API,就是通过这个拦截器实现的。注意:尽量避免在Action中直接访问Servlet API,这样会导致Action与Servlet的高耦合。

 

roles

这是一个JAAS(Java Authentication and Authorization Service,Java授权和认证服务)拦截器,只有当浏览者取得合适的授权后,才可以调用被该拦截器拦截的Action。

 

timer

这 个拦截器负责输出Action的执行时间,这个拦截器在分析该Action的性能瓶颈时比较有用。

 

token

这个拦截器主要 用于阻止重复提交,它检查传到Action中的token,从而防止多次提交。

 

token-session

这个拦截器的作用 与前一个基本类似,只是它把token保存在HttpSession中。

 

validation

通过执行在 xxxAction-validation.xml中定义的校验器,从而完成数据校验。

 

workflow

这个拦截器负责调用 Action类中的validate方法,如果校验失败,则返回input的逻辑视图。 

 

大部分时候,开发者无需手动控制这些拦截器,因为struts-default.xml文件中已经配置了这些拦截器,只要我们定义的包继承 了系统的struts-default包,就可以直接使用这些拦截器。