在之前的工作和学习中总是会遇到表单重复提交的问题,使用了网上的各种解决方法 js,禁用提交按钮,阻止用户后退等操作,但是效果总有一些欠缺。在这里参考了某位老师的意见,决定使用session和自定义表单的形式进行解决。
1、实现思路:
在页面存放一个含有唯一值key value对将其存放在session(这里采用jsp自定义标签的方式进行实现,避免在jsp页面中写很多的java脚本 导致页面混乱)
在提交表单时,后台的处理逻辑获取request中的session 并去取出其中指定的值,第一次获取对应的值后就将其对应的值设置为null,则用户无论以(刷新,后退,重新)等方式进行再次提交。则第二次或者多次提交到后台获取的数据为null时,则判断为重复提交。
2、jsp自定义标签的原理
3、编写jsp的自定义标签
继承SimplTagSupport类,并重新覆盖其中的doTag对象,在其中获取session,并设置唯一的key-value对
<code>
/**
* 防止表单重复提交的jsp标签类
* @author xieqx
*
*/
public class TokenTag extends SimpleTagSupport{
//在调用方法之前,该类对象已经被注入了PageContext(可以从其中获取session) //该对象由setJspContext()方法调用 返回JspContext (其实返回的真实类型为PageContext //JspContext 其实为PageContext的父类)
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext)getJspContext(); //获取jsp的九大域对象
HttpSession session = pageContext.getSession();
session.setAttribute("token", UUID.randomUUID().toString());
}
}
</code>
4、编写tld文件
<code>
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="/xml/ns/j2ee"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/xml/ns/j2ee /xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<!-- tld版本 -->
<tlib-version>1.0</tlib-version>
<!-- 在jsp页面引入该标签时使用的前缀 -->
<short-name>xieqx</short-name>
<!-- 指定使用该标签库中标签的URI -->
<uri>/xiu</uri>
<tag>
<!-- 标签名称 -->
<name>token</name>
<!-- 标签的实现类 -->
<tag-class>cn.xiu.simpletag.TokenTag</tag-class>
<!-- 此标签的主体部分的内容。
其值可为
scriptless 标签中所含有的内容可以为 文本、EL和JSP语言
tagdependent 标签主题内容由标签处理类来解析, 标签主体所有代码原封不动地传递给标签处理类
意思是 如果标签主题中的内容为 <a></a> 等html标签或者el表达式等语言 在页面展示时不进行解析,
而是直接传递给标签处理泪
empty 空标记,即起始标记和结束标记之间没有内容
默认为empty -->
<body-content>empty</body-content>
</tag>
</taglib>
</code>
有关tld文件中标签元素的详细内容请参考:/u012031380/article/details/53517400
将编写好的tld文件放置到项目的WEB-INF下在项目启动后会自动的加载。
5、在jsp页面中进行引入相应的标签进行使用
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 引入要使用的自定义的jsp标签 --> <%@ taglib uri="/xiu" prefix="xieqx" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'simpleTag2.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<xieqx:token /> //使用自定义的token标签
<input type="button" value="提交" οnclick="submit();" />
<script type="text/javascript">
function submit(){
window.location.href="${pageContext.request.contextPath}/token.do";
}
</script>
</body>
</html>
5、使用servlet作为后台处理类
public class TokenServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = req.getSession();
String uuid = (String) session.getAttribute("token");
if(uuid!=null){
//销毁session 防止表单重复提交
System.out.println("模拟表单第一次提交"+uuid);
session.setAttribute("token", null);
}else{
System.out.println("表单重复提交!!!");
}
}
}
6、调试运行
第一次访问:
以后的所有提交操作均显示表单重复提交
演示完毕,有啥差错大家请指教。