spring boot 防止重复提交实现方法详解
本文实例讲述了springboot防止重复提交实现方法。分享给大家供大家参考,具体如下:
服务器端实现方案:同一客户端在2秒内对同一URL的提交视为重复提交
上代码吧
pom.xml
4.0.0 com.example springboot-repeat-submit 1.0 jar org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aop com.google.guava guava 24.0-jre org.springframework.boot spring-boot-maven-plugin
Application.java
packagecom; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; /** *@authorwww.gaozz.club *@功能描述防重复提交 *@date2018-08-26 */ @SpringBootApplication publicclassApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(Application.class,args); } }
自定义注解NoRepeatSubmit.java
packagecom.common; importjava.lang.annotation.ElementType; importjava.lang.annotation.Retention; importjava.lang.annotation.RetentionPolicy; importjava.lang.annotation.Target; @Target(ElementType.METHOD)//作用到方法上 @Retention(RetentionPolicy.RUNTIME)//运行时有效 /** *@功能描述防止重复提交标记注解 *@authorwww.gaozz.club *@date2018-08-26 */ public@interfaceNoRepeatSubmit{ }
aop解析注解NoRepeatSubmitAop.java
packagecom.common; importjavax.servlet.http.HttpServletRequest; importorg.apache.commons.logging.Log; importorg.apache.commons.logging.LogFactory; importorg.aspectj.lang.ProceedingJoinPoint; importorg.aspectj.lang.annotation.Around; importorg.aspectj.lang.annotation.Aspect; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Component; importorg.springframework.web.context.request.RequestContextHolder; importorg.springframework.web.context.request.ServletRequestAttributes; importcom.google.common.cache.Cache; @Aspect @Component /** *@功能描述aop解析注解 *@authorwww.gaozz.club *@date2018-08-26 */ publicclassNoRepeatSubmitAop{ privateLoglogger=LogFactory.getLog(getClass()); @Autowired privateCachecache; @Around("execution(*com.example..*Controller.*(..))&&@annotation(nrs)") publicObjectarround(ProceedingJoinPointpjp,NoRepeatSubmitnrs){ try{ ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); StringsessionId=RequestContextHolder.getRequestAttributes().getSessionId(); HttpServletRequestrequest=attributes.getRequest(); Stringkey=sessionId+"-"+request.getServletPath(); if(cache.getIfPresent(key)==null){//如果缓存中有这个url视为重复提交 Objecto=pjp.proceed(); cache.put(key,0); returno; }else{ logger.error("重复提交"); returnnull; } }catch(Throwablee){ e.printStackTrace(); logger.error("验证重复提交时出现未知异常!"); return"{\"code\":-889,\"message\":\"验证重复提交时出现未知异常!\"}"; } } }
缓存类
packagecom.common; importjava.util.concurrent.TimeUnit; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importcom.google.common.cache.Cache; importcom.google.common.cache.CacheBuilder; @Configuration /** *@功能描述内存缓存 *@authorwww.gaozz.club *@date2018-08-26 */ publicclassUrlCache{ @Bean publicCachegetCache(){ returnCacheBuilder.newBuilder().expireAfterWrite(2L,TimeUnit.SECONDS).build();//缓存有效期为2秒 } }
测试Controller
packagecom.example; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; importcom.common.NoRepeatSubmit; /** *@功能描述测试Controller *@authorwww.gaozz.club *@date2018-08-26 */ @RestController publicclassTestController{ @RequestMapping("/test") @NoRepeatSubmit publicStringtest(){ return("程序逻辑返回"); } }
浏览器输入http://localhost:8080/test
然后F5刷新查看效果
以下为新版内容:解决了程序集群部署时请求可能会落到多台机器上的问题,把内存缓存换成了redis
application.yml
spring: redis: host:192.168.1.92 port:6379 password:123456
RedisConfig.java
packagecom.common; importorg.springframework.boot.context.properties.ConfigurationProperties; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.data.redis.connection.RedisStandaloneConfiguration; importorg.springframework.data.redis.connection.jedis.JedisClientConfiguration; importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory; importorg.springframework.data.redis.core.RedisTemplate; @Configuration publicclassRedisConfig{ @Bean @ConfigurationProperties(prefix="spring.redis") publicJedisConnectionFactorygetConnectionFactory(){ returnnewJedisConnectionFactory(newRedisStandaloneConfiguration(),JedisClientConfiguration.builder().build()); } @BeanRedisTemplate getRedisTemplate(){ RedisTemplate redisTemplate=newRedisTemplate (); redisTemplate.setConnectionFactory(getConnectionFactory()); returnredisTemplate; } }
调整切面类NoRepeatSubmitAop.java
packagecom.common; importjavax.servlet.http.HttpServletRequest; importorg.apache.commons.logging.Log; importorg.apache.commons.logging.LogFactory; importorg.aspectj.lang.ProceedingJoinPoint; importorg.aspectj.lang.annotation.Around; importorg.aspectj.lang.annotation.Aspect; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.data.redis.core.RedisTemplate; importorg.springframework.data.redis.core.ValueOperations; importorg.springframework.stereotype.Component; importorg.springframework.web.context.request.RequestContextHolder; importorg.springframework.web.context.request.ServletRequestAttributes; @Aspect @Component /** *@功能描述aop解析注解 *@authorwww.gaozz.club *@date2018-11-02 */ publicclassNoRepeatSubmitAop{ privateLoglogger=LogFactory.getLog(getClass()); @Autowired privateRedisTemplatetemplate; @Around("execution(*com.example..*Controller.*(..))&&@annotation(nrs)") publicObjectarround(ProceedingJoinPointpjp,NoRepeatSubmitnrs){ ValueOperations opsForValue=template.opsForValue(); try{ ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); StringsessionId=RequestContextHolder.getRequestAttributes().getSessionId(); HttpServletRequestrequest=attributes.getRequest(); Stringkey=sessionId+"-"+request.getServletPath(); if(opsForValue.get(key)==null){//如果缓存中有这个url视为重复提交 Objecto=pjp.proceed(); opsForValue.set(key,0,2,TimeUnit.SECONDS); returno; }else{ logger.error("重复提交"); returnnull; } }catch(Throwablee){ e.printStackTrace(); logger.error("验证重复提交时出现未知异常!"); return"{\"code\":-889,\"message\":\"验证重复提交时出现未知异常!\"}"; } } }
附:GitHub源码地址:https://github.com/gzz2017gzz/spring-boot2-example/tree/master/54-spring-boot-repeat-submit-single
更多关于java相关内容感兴趣的读者可查看本站专题:《Spring框架入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。