如何使用Struts 2防止表单重复提交?

  【IT168技术】 用户重复提交表单在某些场合将会造成非常严重的后果。例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次。因此,重复提交表单会对你的系统带来逻辑影响,必须采取一些措施防止这类情况的发生。

  用户重复提交同一个HTML表单的原因有:快速多次点击提交按钮;提交表单后按下浏览器的刷新按钮。

  设置Struts 2的预防表单重复提交的功能

  Struts 2已经内置了能够防止用户重复提交同一个HTML表单的功能。它的工作原理:让服务器生成一个唯一标记,并在服务器和表单里各保存一份这个标记的副本。此后,在用户提交表单的时候,表单里的标记将随着其他请求参数一起发送到服务器,服务器将对他收到的标记和它留存的标记进行比较。如果两者匹配,这次提交的表单被认为是有效的,服务器将对之做出必要的处理并重新设置一个新标记。随后,提交相同的表单就会失败,因为服务器上的标记已经重置。

  Struts 2标签中的token标签,可以用来生成一个独一无二的标记。这个标记必须嵌套在form标签中使用,它会在表单里插入一个隐藏字段并把标记保存到HttpSession对象里。toke标签必须与Token或Token Session拦截器配合使用,两个拦截器都能对token标签进行处理。Token拦截器遇到重复提交表单的情况,会返回一个"invalid.token"结果并加上一个动作级别的错误。Token Session拦截器扩展了Token拦截器并提供了一种更复杂的服务,它采取的做法与Token拦截器不同,它只是阻断了后续的提交,这样用户不提交多少次,就好像只是提交了一次。

  示例:使用Token拦截器预防表单重复提交

  配置struts.xml文件,声明动作

<? xml version="1.0" encoding="UTF-8"  ?> <! DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
    
< package  name ="avoidPackage"  extends ="struts-default" >
        
< action  name ="avoid"  class ="struts2.action.AvoidAction" >
            
< interceptor-ref  name ="token" ></ interceptor-ref >             
             < interceptor-ref  name ="defaultStack" ></ interceptor-ref >
             
< result  name ="invalid.token" > /error.jsp </ result >
            
< result  name ="input" > /input.jsp </ result >
            
< result  name ="success" > /output.jsp </ result >         
        </ action >
    
</ package >
</ struts >

   此时,需要在动作的声明中,为动作添加token拦截器,因为token拦截器不在defaultStack拦截器栈中,注意,需要将拦截器放在拦截器栈的第一位,这是因为判断表单是否被重复提交的逻辑应该在表单处理前。

  创建动作类

public   class  AvoidAction  extends  ActionSupport {
    
private   static   final   long  serialVersionUID  =   2676453800249807631L ;
        
private  String username;
    
private  Date birthday;
        
public  String getUsername() {
        
return  username;
    }
    
public   void  setUsername(String username) {
        
this .username  =  username;
    }
    
public  Date getBirthday() {
        
return  birthday;
    }
    
public   void  setBirthday(Date birthday) {
        
this .birthday  =  birthday;
    }
        @Override
    
public  String execute()
    {
        
try  {
            Thread.sleep(
4000 );
        } 
catch  (InterruptedException e) {
            e.printStackTrace();
        }
                
return  SUCCESS;
    }
}

  这个动作逻辑处理为挂起4秒钟,让我们有机会多次点击提交按钮,测试效果。

猜你喜欢

转载自q364035622.iteye.com/blog/1902289