页面刷新重复提交请求如何解决

前言

页面刷新重复提交请求这个问题在Web开发中很常见。在很多时候我们都忽略了这个问题。

那么这个问题的如何触发的呢?
一般无非就是你按F5或者在页面鼠标右键点击刷新。可能会触发这个问题。
那么为什么会出现这种问题呢。这个是浏览器的原因。浏览器中有一个history对象,history中有一个State。当我们发送请求的时候,会将请求存入history的State中。这个State的结构就像一个栈。拥有着后进先出的特性。也正是因为这个对象,我们才能能够在浏览器中执行后退,前进等操作。

但是你比方说,如果我们的上一次请求是往数据库中insert一条语句。那么不断刷新页面,就会不断去执行这个Insert逻辑。所以一般我们对数据库进行修改操作后,会重定向当前页面,那么重定向的这个url就会存入State的栈顶了。这时候你再怎么刷新页面,按F5都只是重定向当前页面,而不是insert了。因为history对象的State栈顶元素被替换成了你重定向的那个请求。
在这里插入图片描述

最简单的方法就是禁用F5按键和鼠标右键刷新事件。这个在js层面就可以做的。但这种方式也太粗暴了,不推荐使用

那么这个问题如何解决呢?
核心思想就是Post/Redirect/Get模式

方法一:使用html5的新特性

在html5中新增了两个方法,一个是replaceState,另外一个是pushState。
前面我们已经知道,每当我们发送一次请求,就会往State中存入一条记录。这两个方法能够修改history中State的值。也就是说你可以手动替换栈顶元素。

  • replaceState:顾名思义是将栈顶的State进行替换
  • pushState:是往栈里面添加一条请求
    当你做插入操作后,用该方法替换State的值为查询逻辑。那么你刷新页面,也就不会提交请求了。
    但是这种方式有缺陷。使用这种方式必须要确认你所使用浏览器版本是支持这个html5新特性的。否则这种方法是无效的。
    网上提供了一些方法,让低版本的浏览器也能使用这两个方法。在界面导入history.js脚本。但是这种方法并不好用。不一定能生效。

在页面加载的时候执行如下代码

if(replaceState){
  history.replaceState(null,null,'当前页面路径');
}

更多repalceState的详细方法大家可以自行去了解一下。

方法二:使用Token

Token是什么意思呢?字面意思就是令牌。先来说一下它的实现方式。这种方式比较适合前端页面是JSP页面的。如果是html也可以使用。但是这种方式有一个限制。那就是你发送请求页面发生了跳转。一般应用于那种页面发生跳转的场景。
如果说发送请求后,你的页面依然是在当前页面。那么这种方式是不可行的。
这里以前端页面为JSP为例,因为JSP中可以写Java代码,获取Session较为方便,当然了,HTML也能够获取Seession,但是稍微复杂一点。感兴趣的可以自己搜一下。
在这里插入图片描述

首先,我们先生成一个随机字符串,将这个字符串存入Session中和表单隐藏域中。然后在前端控制层,也就是Controller层或者Action层。

前端JSP页面加上如下代码

<%
String token=UUID.getId();
request.getSession.SetAttribute("tocken",token);
%>

<html>
   <form>
      <input type='hidden' name='token' value='<%=token%>'/>
   </form>
</html>

Controller层代码


String token=(String) req.getSession().getAttribute("token");
String f = req.getParameter("token");
	if(f.equals(token)){
             //说明是表单a提交的请求,执行insert逻辑
             insert();
             req.getSession().removeAttribute("token");
    }else{
               //重定向当前页面  
    }

原理是什么呢?当第一次插入逻辑执行成功后,删除session中的值,这个时候你刷新页面重新发送请求session中的token值是null。因此他就会走else逻辑。这个时候你重定向当前页面就好了。

方法三:使用ajax

ajax是一种异步刷新的技术。非常的方便。个人觉得这种方式是最好的。无论你发送请求后是在当前页面还是跳转了页面。这种方式都是比较不错的。但前提是你比较熟悉ajax的使用。

$.ajax{
  url:
  data:
  datatype:
  success(data){
     //假设你执行的是一个insert操作,现在返回了一个标志位成功
     if(data==true){
        //从定向页面,根据场景可以是当前页面也可以是其他页面
        location.herf="";
     }
  }
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值