使用redis防止重复提交

 

其实主要思路是他的https://blog.csdn.net/u013378306/article/details/52944780

主要目前我的情况是,前后端分离的,前端没有session ,所以使用redis来存放数据。

自定义注解

package com.cdp.api.onboarding.interceptor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 一个用户 相同url 同时提交 相同数据 验证
* @author Administrator
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SameUrlData { }

自定义拦截器

package com.cdp.api.onboarding.interceptor;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.alibaba.druid.util.IOUtils;
import com.cdp.api.common.util.CommonUtil;
import com.cdp.api.common.util.DateUtil;
import com.cdp.api.common.util.JedisUtil;
import com.cdp.api.common.util.StringUtil; /**
*
* @author Administrator
*
*/
public class SameUrlDataInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory
.getLogger(CommonUtil.class); @Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
SameUrlData annotation = method.getAnnotation(SameUrlData.class);
if (annotation != null) {
if (repeatDataValidator(request)) {
logger.debug(DateUtil
.getTimeString_Now("yyyy-MM-dd HH:mm:ss")
+ " -- 重复请求 -- ");
return false;
}// 如果重复相同数据
else
return true;
}
return true;
} else {
return super.preHandle(request, response, handler);
}
} /**
* 验证同一个url数据是否相同提交 ,相同返回true
*
* @param request
* @return
* @throws Exception
*/
public boolean repeatDataValidator(HttpServletRequest request)
throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(
request.getInputStream()));
// 判断body
String body = IOUtils.read(reader);
String url = request.getRequestURI();
Map<String, String> map = new HashMap<String, String>();
map.put(url, body);
String nowUrlParams = map.toString();// String preUrlParams = JedisUtil.getFromRedis(url);
if (StringUtil.isNullOrBlank(preUrlParams))// 如果上一个数据为null,表示还没有访问页面
{
// 扔redis
JedisUtil.saveInRedis(url, nowUrlParams, 60);
logger.debug(DateUtil.getTimeString_Now("yyyy-MM-dd HH:mm:ss")
+ " -- 设置preUrlParams -- " + nowUrlParams);
return false;
} else// 否则,已经访问过页面
{
if (preUrlParams.toString().equals(nowUrlParams))// 如果上次url+数据和本次url+数据相同,则表示重复添加数据
{
logger.debug(DateUtil.getTimeString_Now("yyyy-MM-dd HH:mm:ss")
+ " -- 重复提交preUrlParams -- ");
return true;
} else// 如果上次 url+数据 和本次url加数据不同,则不是重复提交
{
logger.debug(DateUtil.getTimeString_Now("yyyy-MM-dd HH:mm:ss")
+ " -- 重新设置preUrlParams -- " + nowUrlParams);
JedisUtil.saveInRedis(url, nowUrlParams, 60);
return false;
} }
} }

拦截器的配置

<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login" />
<mvc:exclude-mapping path="/token/get" />
<mvc:exclude-mapping path="/file/**" />
<mvc:exclude-mapping path="/wx/**" />
<mvc:exclude-mapping path="/wxCompany/**" />
<mvc:exclude-mapping path="/wxOnFamily/**" />
<mvc:exclude-mapping path="/wxlogin/**" />
<mvc:exclude-mapping path="/wxMaterial/**" />
<mvc:exclude-mapping path="/wxOfferManagement/**" />
<mvc:exclude-mapping path="/wxOnEmployee/**" />
<mvc:exclude-mapping path="/wxOnEducation/**" />
<mvc:exclude-mapping path="/wxOnTraining/**" />
<mvc:exclude-mapping path="/wxOnWork/**" />
<mvc:exclude-mapping path="/wxTeam/**" />
<mvc:exclude-mapping path="/wxTemplatePage/**" />
<mvc:exclude-mapping path="/wxWelcomePage/**" />
<mvc:exclude-mapping path="/wxIdPhoto/**" />
<mvc:exclude-mapping path="/offer/excel_offer/import" />
<bean class="com.cdp.api.onboarding.interceptor.SameUrlDataInterceptor"></bean>
</mvc:interceptor>

ps,使用的时候要在controller加上注解

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

使用redis防止重复提交的更多相关文章

  1. redis防止重复提交

    public interface DistributedLock { boolean getLock(String var1, String var2, int var3);//加锁 void unL ...

  2. Java使用Redis实现分布式锁来防止重复提交问题

    如何用消息系统避免分布式事务? - 少年阿宾 - BlogJavahttp://www.blogjava.net/stevenjohn/archive/2018/01/04/433004.html [ ...

  3. 【Redis使用系列】使用Redis做防止重复提交

    前言 在平时的开发中我们都需要处理重复提交的问题,避免业务出错或者产生脏数据,虽然可以通过前端控制但这并不是可以完全避免,最好的方式还是前后端均进行控制,这样的话就可以更有效,尽可能全面的去减少错误的 ...

  4. 浅谈C#在网络波动时防重复提交

    前几天,公司数据库出现了两条相同的数据,而且时间相同(毫秒也相同).排查原因,发现是网络波动造成了重复提交. 由于网络波动而重复提交的例子也比较多: 网络上,防重复提交的方法也很多,使用redis锁, ...

  5. Restful api 防止重复提交

    当前很多网站是前后分离的,前端(android,iso,h5)通过restful API 调用 后端服务器,这就存在一个问题,对于创建操作,比如购买某个商品,如果由于某种原因,手抖,控件bug,网络错 ...

  6. springmvc防止重复提交拦截器

    一.拦截器实现,ResubmitInterceptorHandler.java import org.apache.commons.lang3.StringUtils; import org.spri ...

  7. 防CSRF攻击:一场由重复提交的问题引发的前端后端测试口水战

    重复提交,这是一直以来都会存在的问题,当在网站某个接口调用缓慢的时候就会有可能引起表单重复提交的问题,不论form提交,还是ajax提交都会有这样的问题,最近在某社交app上看到这么一幕,这个团队没有 ...

  8. Token机制,防止web页面重复提交

    1.业务要求:页面的数据只能被点击提交一次 2.发生原因: 由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交 3.解决办法: 集群环境:采用token加redis(redis单线 ...

  9. 由防止表单重复提交引发的一系列问题--servletRequest的复制、body值的获取

    @Time:2019年1月4日 16:19:19 @Author:QGuo   背景:最开始打算写个防止表单重复提交的拦截器:网上见到一种不错的方式,比较合适前后端分离,校验在后台实现: 我在此基础上 ...

随机推荐

  1. 织梦后台系统设置在PHP5.4环境中不能保存中文参数的解决方法

    在没用PHP5.4的环境做Dede后台的时候,织梦58一直没有遇到这个问题,昨天上传一个新的模版到空间去测试发现后台的系统基本参数设置中所有的中文内容都无法保存,关于这个问题,其实以前也听说过,知识一 ...

  2. 异步处理的框架Sanic的使用方法和小技巧

    Sanic是异步处理的框架,运用Sanic可以开发快速异步响应的web程序.想必大家看到这个都会比较期待和兴奋. 那么如何使用Sanic来实现快速响应呢?我们先来看一看Sanic的基本介绍. Sani ...

  3. 七:mvc使用CodeFirst(代码优先)创建数据库

    1. 理解EF CodeFirst模式特点 2. 使用CodeFirst模式生成数据库 1. CodeFirst模式(代码优先) Code First是Entity Framework提供的一种新的编 ...

  4. web开发:javascript动画

    一.鼠标事件 二.js盒模型 三.鼠标拖拽 四.键盘事件 五.其他时间应用 六.定时器 七.定时器案例 八.随机数 一.鼠标事件 <!DOCTYPE html> <html> ...

  5. C 动态内存申请

    例子: int *p=0; int number=0; scanf("%d",&number); p = (int*)malloc(number*sizeof(int));

  6. MySQL No Install zip安装方法

    解压 解压安装包到一个目录,比如:D:\Database\mysql-5.1.55 配置 创建配置文件 创建一个my.ini文件,MYSQL目录下有几个my开头的ini文件,是针对不同配置使用,具体可 ...

  7. zabbix内存溢出解决方法

    1406:20180802:183248.783 __mem_malloc: skipped 0 asked 48 skip_min 4294967295 skip_max 0 1406:201808 ...

  8. python_函数作用域

    py文件:全局作用域 函数:局部作用域 一个函数是一个作用域 def func(): x = 9 print(x) func() print(x) 作用域中查找数据规则:优先在自己的作用域找数据,自己 ...

  9. java.util.Stack

    import java.util.Stack; public class Test { public static void main(String[] args) { Stack stack = n ...

  10. java线程基础方法详解

    一.线程状态转换 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行 ...