在项目开发过程中发现了一个问题。
在点击添加按钮后,路径显示的是add函数,而界面是add.jsp,此时刷新页面会导致再次提交与刚才一模一样的数据到数据库。或者在添加完毕后,浏览器后退然后点击提交,也会导致一样的问题。
在网上找了很多资料。
(一)很多人推荐使用struts的token机制。方法很简单。
1.在jsp的头部引用标签库:<%@taglib uri="/struts-tags" prefix="s" %>
需要提交的form中添加标签:<s:token\>
2.在stuts.xml中添加拦截器:
<action name="AMe" class="messageAction" method="save">
<result name="success">/page/contact.jsp</result><!--首次提交添加成功后跳转界面-->
<interceptor-ref name="defaultStack" ></interceptor-ref><!--默认的拦截器-->
<interceptor-ref name="token" ></interceptor-ref><!--添加token-->
<result name="invalid.token" type="redirectAction">Erro</result><!--当重复提交出现时的跳转,name为固定值,可以重定向到另外一个action,也可以直接跳转到错误界面-->
</action>
3.出现的问题:
进入添加页面→输入数据,点击提交→提交成功→刷新界面→触发token,跳转到重复提交的界面。
点击查询按钮,触发查询的action→出错。
重新进入添加页面→输入数据,点击提交→出错。
原因不明,也许以后能够解决。
(二)使用类似于token的原理,但是不采用token。
在进入添加页面时调用action,手动生成随机令牌,存入session中,并传值给jsp,然后再跳转至添加界面。
在add的action中,取出jsp中存进去的令牌,取出session中的令牌,比较。相同则为首次提交,进行add操作,然后清除session,并清除所有的添加参数(防止影响到其他的action)。不同则为重复提交,清除所有参数并跳转至错误界面,或重定向到别的action。
1.书写进入add.jsp的函数:
/*进入添加页面时生成一个随机数*/
public String showtosave(){
msg=null;
UUID uuid = UUID.randomUUID();//生成随机数
ActionContext.getContext().getSession().put("token",uuid.toString());//存放至session
tmp=uuid.toString();
return SUCCESS;
}
上述函数需要引入两个包:
import java.util.UUID;
import javax.servlet.http.HttpSession;
2.在struts.xml中配置showtosave函数:
<action name="STSME" class="messageAction" method="showtosave">
<result name="success">/page/contact.jsp</result><!--跳转至添加界面,即上述所提的add.jsp-->
</action>
3.在jsp中加入隐藏域:
<input type="hidden" value="${tmp}">
4.添加add的action:
public String save(){
String token = (String)ActionContext.getContext().getSession().get("token");
if(StringUtils.isNotBlank(token)&&token.equals(tmp)){//令牌存在且且是第一次提交
messageBiz.addMe(messages);//数据库插入操作
msg="留言成功!";
ActionContext.getContext().getSession().remove("token");//删除session中的记录
messages=null;//删除所有参数
return SUCCESS;
}
else{//重复提交
messages=null;//删除所有参数
msg=null;
return "duplicate";
}
}
5.配置save的struts.xml
<action name="AMe" class="messageAction" method="save">
<result name="success">/page/contact.jsp</result>
<result name="duplicate">/page/index.jsp</result>
</action>
6.结果
添加后刷新,再次点击提交,后退后点击提交都可以进行判断,不会引发重复提交。