Struts2防止表单重复提交

1.    预备知识:

a)      拦截器配置

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

我们可以在<package/>中增加这样一行<default-interceptor-ref name="拦截器的名字"/>即表示将该拦截器作为整个包的默认拦截器,它会自动附加到我们的每一个Action中。并且在一个<package/>中只能使用<default-interceptor-ref/>定义一个默认的拦截器。

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

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

若还想使用默认拦截器,则只能再通过手工方式导入<interceptor-ref name="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. 服务器端跳转是由客户端发送一个请求,请求一个服务器资源——JSPServlet——,这个资源又将请求转到另一个服务器资源,然后再给客户端发送一个响应,也就是说服务器端跳转是客户端发送一次请求,服务器端给出一次响应;而客户端跳转的流程则不同。客户端同样是发送一个请求给服务器端资源,这个服务器资源会首先给客户端一个响应,客户端再根据这个响应当中所包含的地址,再次向服务器端发送一个请求,也就是说客户端跳转是两次请求,两次响应;

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

 

2.开始解决

使用struts2  token拦截器

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

Jsp页面部分代码:

 

在表单提交页面写上<s:token/>

<s:form action="add" method="post">

    <s:token /><!-- 防止表单重复提交 -->

    <s:textfield name="userName" label="用户名"></s:textfield><br/>

    <s:password name="password" label="密码"></s:password><br/>

    <s:submit />

</s:form>

 

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

<action name="*" class="tutorial.UploadFiles" method="{1}">
<
interceptor-ref name="token"></interceptor-ref>

<result name="filesShow">

/filesShow.jsp

</result>

 

Struts2的内置拦截器:

 

<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>

<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>

<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>

<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>

<interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />

<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />

<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />

<interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>

<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>

<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>

<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>

<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>

<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

<interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>

<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>

<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>

<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>

<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>

<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>

<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>

<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>

<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>

<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>

<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />

<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />

<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />

<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />

<interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />

<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />

<interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />

 

 

 

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

名称

描述

 

alias

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

 

autowiring

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

 

chain

构建一个Action链,使当 Action可以访问前一个Action的属性,一般和<result type="chain" .../>一起使用。

 

conversionError

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

 

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>标签下<param>标签中的参数传入action

 

scope

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

 

servlet-config

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

 

roles

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

 

timer

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

 

token

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

 

token-session

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

 

validation

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

 

workflow

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

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值