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());
}
@Bean
RedisTemplategetRedisTemplate(){
RedisTemplateredisTemplate=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){
ValueOperationsopsForValue=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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。