当每次填写完表单后单击提交后,struts中action执行相关业务逻辑,通过forward对象转到某个页面。这时若刷新页面后,会再执行同样的逻辑。比如录数据到数据库,按照上面的情况,数据库中会有两条同样的数据。为了避免这种情况,有几种解决办法:
解决方案:
1.重定向,在配置文件里配置redirect属性<forwardredirect="true"path="/xxx/xxx.jsp">,重定向到xxx.jsp。这种情况下会丢失request范围内的参数,若xxx.jsp不要求这些参数就可以,如操作的数据保存在session范围内,就不会影响整体效果。但还是有弊端。
2.采用struts解决方案
防止重复提交原理:
首先,在页面访问的时候server端产生一个标志位,其保存在session中,同时该标志位放到访问的页面的某个元素中(通常为隐藏域);
其次,在session存在的有效时间内,没有其它操作时其值保持不变,当提交表单到server端时,会判断client端提交过来的标志位和server端的标志位的值是否相等;
最后,判断标志位的值,如果相等,则执行自己期望的操作;如果不相等,则转向指定的页面
实例:
- Index.jsp
<%@page language="java" contentType="text/html; charset=utf-8"%>
<!-- 首先要导入struts2的标签库 -->
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPEhtml>
<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=ISO-8859-1">
<title>Inserttitle here</title>
</head>
<body>
<form name="myform"action="student_add" method="post">
<!-- 此处必须增加token表签-->
<s:token></s:token>
学生姓名:<input type="text" name="sname" value="苹果"/><br />
密码:<input type="text" name="pwd"value="a" /><br />
入学日期:<input type="text" name="enrolldate"value="2015-09-09" /><br />
地区:<input type="radio" name="addr" value="湖南" />湖南
<inputtype="radio" name="addr" value="广东" />广东
<inputtype="radio" name="addr" value="福建" />福建
<inputtype="radio" name="addr" value="四川" />四川
<inputtype="radio" name="addr" value="重庆" />重庆
<br />
<inputtype="submit" value="添加" />
</form>
</body>
</html>
2、在struts配置文件中增加token拦截器。(token 和 token-session 拦截器的启用,是在 struts.xml配置文件中,既可以为包启用,也可以单独为某个 action 启用)
需要注意一点的是:type类型必须为转发类型
<?xmlversion="1.0" encoding="UTF-8" ?>
<!DOCTYPE strutsPUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constantname="struts.enable.DynamicMethodInvocation" value="true"/>
<constantname="struts.devMode" value="true" />
<packagename="default" namespace="/"extends="struts-default">
<actionname="student_*" class="com.yc.action.StudentAction"method="{1}">
<!-- 在action中配置token拦截器 和invalid.token 的结果 -->
<interceptor-refname="defaultStack"></interceptor-ref>
<interceptor-refname="token">
<paramname="includeMethods">add</param>
</interceptor-ref>
<result name="invalid.token" type="dispatcher">/Token_error.jsp</result>
</action>
</package>
</struts>
- Token_error.jsp
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPEhtml>
<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Inserttitle here</title>
</head>
<body>
<s:actionerror/> |
| // | 打印错误信息 |
</body>
</html>
当第一次请求时多了两个隐藏域