package com.future.interceptor;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import com.baoqilai.scp.web.RestResultGenerator;
import com.future.shiro.ShiroUtils;
import com.google.common.cache.Cache; @Aspect
@Component
public class NoRepeatSubmitAop { private static final Logger logger = LoggerFactory.getLogger(NoRepeatSubmitAop.class); @Autowired
private Cache<String, Integer> cache; @Around("execution(* com.future.controller.*.*.*(..))&& @annotation(nos)")
public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nos) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String sessionId = ShiroUtils.getSession().getId().toString();
HttpServletRequest request = attributes.getRequest();
String key = sessionId + "-" + request.getServletPath();
if (cache.getIfPresent(key) != null) {
logger.error("重复提交");
return RestResultGenerator.genErrorResult("重复请求,请稍后再试");
}
// 如果是第一次请求,就将 key 当前对象压入缓存中
cache.put(key, 0);
try {
return pjp.proceed();
} catch (Throwable throwable) {
logger.error("验证重复提交时出现未知异常!");
return RestResultGenerator.genErrorResult("验证重复提交时出现未知异常!");
} finally {
cache.invalidate(key);
} } }
package com.future.interceptor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @功能描述 防止重复提交标记注解
* @author Administrator
*
*/
@Target(ElementType.METHOD) // 作用到方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface NoRepeatSubmit { }
package com.future.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; @Configuration
public class UrlCache { @Bean
public Cache<String, Integer> getCache() {
// return CacheBuilder.newBuilder().expireAfterWrite(2L, TimeUnit.SECONDS).build();// 缓存有效期为2秒
return CacheBuilder.newBuilder().build();// 不设置缓存有效期
}
}
@RequestMapping(value = "/test", method = RequestMethod.POST)
@NoRepeatSubmit
public RestResult test() {
int res=6;
if(res>0){
return RestResultGenerator.genSuccessResult();
}
return RestResultGenerator.genErrorResult("核单失败");
}
 <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.0-jre</version>
</dependency>

来自:https://www.jianshu.com/p/09c6b05b670a

https://blog.csdn.net/memmsc/article/details/80837996 分布式参考

spring boot 重复提交的更多相关文章

  1. spring boot 开发 提交form表单出错

    提交表单时,字段有的没有值,springboot 会报错. org.springframework.validation.BindException: org.springframework.vali ...

  2. Spring boot POST 提交错误 Request header is too large

    解决方法 application.yml server: # 单位 KB max-http-header-size: 100000 java.lang.IllegalArgumentException ...

  3. spring boot 学习(七)小工具篇:表单重复提交

    注解 + 拦截器:解决表单重复提交 前言 学习 Spring Boot 中,我想将我在项目中添加几个我在 SpringMVC 框架中常用的工具类(主要都是涉及到 Spring AOP 部分知识).比如 ...

  4. Spring Boot (一) 校验表单重复提交

    一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...

  5. spring boot 防止重复提交

    服务器端实现方案:同一客户端在2秒内对同一URL的提交视为重复提交 上代码吧 pom.xml <?xml version="1.0" encoding="UTF-8 ...

  6. Spring Boot 如何防止重复提交?

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 在传统的web项目中,防止重复提交,通常做法是:后端生成一个唯一的提交令牌(uuid),并存储在服务端.页面提交请求携带这个 ...

  7. Spring MVC拦截器+注解方式实现防止表单重复提交

    原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 注,如果是集群的方式,则需要将token ...

  8. Spring MVC实现防止表单重复提交(转)

    Spring MVC拦截器+注解方式实现防止表单重复提交  

  9. Spring MVC防止数据重复提交

    现实开发中表单重复提交的例子很多,就包括手上这个门户的项目也有这种应用场景,用的次数多,但是总结,这还是第一次. 一.基本原理 使用token,给所有的url加一个拦截器,在拦截器里面用java的UU ...

随机推荐

  1. elementUI表格行的点击事件,点击表格,拿到当前行的数据

    1.绑定事件 2.定义事件 3.点击表格某行的时候,拿到数据]

  2. RzGroupBar

    何分多层 procedure TForm1.FormCreate(Sender: TObject); begin RzGroup1.Items.Clear; RzGroup1.Items.Add.Ca ...

  3. 127.0.0.1和localhost不能正确映射的问题

    可能引起的问题: 检查:分别ping一下127.0.0.1和localhost 以上是正确演示,不匹配的话,ping localhost会返回: 解决方案: 可能1: 在浏览器中打开http://12 ...

  4. ZROI week1

    \[ZROI day1\] \[Grid\] 题目描述 给定一个矩阵,小写字母,求一条路径使得从\((1,1) -> (n,m)\),字典序最小,并且每次只能向右或者向下. 题解 先考虑如果没有 ...

  5. NYOJ 301 递推求值

    第一次写博客,拿个矩阵快速幂练练手吧. 首先什么是快速幂,快速幂是让复杂度由线性降为log n的算法,比如8^1024次方暴力要算1024次,但是矩阵快速幂只算10次就好. 此题只不过是把快速幂的底数 ...

  6. ASP.NET Core学习——2

    Application Startup ASP.NET Core为应用程序提供了处理每个请求的完整控制.Startup类是应用程程的入口(entry point),这个类可以设置配置(configur ...

  7. ubuntu ceph集群安装以及简单使用

    ubuntu ceph安装以及使用 1.安装环境 本文主要根据官方文档使用ubuntu14.04安装ceph集群,并且简单熟悉其基本操作.整个集群包括一个admin节点(admin node,主机名为 ...

  8. Retrofit全攻略——进阶篇

    最近事比较多,距离上次写文章已经过去了一个月了.上一篇文章Retrofit全攻略——基础篇 介绍了Retrofit的基础用法,这篇文章介绍点进阶的用法. 打印网络日志 在开发阶段,为了方便调试,我们需 ...

  9. Junit用断言对控制台输出进行测试

    核心思路: 在测试前,将标准输出定向到ByteArrayOutputStream中去 用输出流文件断言内容 测试完成,将标准输出修改为console 具体操作示例 基本通用复制粘贴操作 public ...

  10. Git 学习第二天(三)

    删除文件: 先新建一个test文件到webgit版本库中,然后 git add            git commit 当然,我们可以在文件夹中删除文件,git 也提供了命令 rm file 此时 ...