怎么在springboot中防止重复提交

这篇文章将为大家详细讲解有关怎么在spring boot中防止重复提交,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

十年的宜城网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。全网营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整宜城建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“宜城网站设计”,“宜城网站推广”以来,每个客户项目都认真落实执行。

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

package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * @author www.gaozz.club
 * @功能描述 防重复提交
 * @date 2018-08-26
 */
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
 }
}

自定义注解NoRepeatSubmit.java

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

aop解析注解NoRepeatSubmitAop.java

package com.common;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
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.google.common.cache.Cache;
@Aspect
@Component
/**
 * @功能描述 aop解析注解
 * @author www.gaozz.club
 * @date 2018-08-26
 */
public class NoRepeatSubmitAop {
 private Log logger = LogFactory.getLog(getClass());
 @Autowired
 private Cache cache;
 @Around("execution(* com.example..*Controller.*(..)) && @annotation(nrs)")
 public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) {
  try {
   ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
   String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
   HttpServletRequest request = attributes.getRequest();
   String key = sessionId + "-" + request.getServletPath();
   if (cache.getIfPresent(key) == null) {// 如果缓存中有这个url视为重复提交
    Object o = pjp.proceed();
    cache.put(key, 0);
    return o;
   } else {
    logger.error("重复提交");
    return null;
   }
  } catch (Throwable e) {
   e.printStackTrace();
   logger.error("验证重复提交时出现未知异常!");
   return "{\"code\":-889,\"message\":\"验证重复提交时出现未知异常!\"}";
  }
 }
}

缓存类

package com.common;
import java.util.concurrent.TimeUnit;
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
/**
 * @功能描述 内存缓存
 * @author www.gaozz.club
 * @date 2018-08-26
 */
public class UrlCache {
 @Bean
 public Cache getCache() {
  return CacheBuilder.newBuilder().expireAfterWrite(2L, TimeUnit.SECONDS).build();// 缓存有效期为2秒
 }
}

测试Controller

package com.example;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.common.NoRepeatSubmit;
/**
 * @功能描述 测试Controller
 * @author www.gaozz.club
 * @date 2018-08-26
 */
@RestController
public class TestController {
 @RequestMapping("/test")
 @NoRepeatSubmit
 public String test() {
  return ("程序逻辑返回");
 }
}

浏览器输入http://localhost:8080/test

然后F5刷新查看效果

怎么在spring boot中防止重复提交

以下为新版内容:解决了程序集群部署时请求可能会落到多台机器上的问题,把内存缓存换成了redis

application.yml

spring:
 redis:
 host: 192.168.1.92
 port: 6379
 password: 123456

RedisConfig.java

package com.common;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfig {
 @Bean
 @ConfigurationProperties(prefix = "spring.redis")
 public JedisConnectionFactory getConnectionFactory() {
  return new JedisConnectionFactory(new RedisStandaloneConfiguration(), JedisClientConfiguration.builder().build());
 }
 @Bean
  RedisTemplate getRedisTemplate() {
  RedisTemplate redisTemplate = new RedisTemplate();
  redisTemplate.setConnectionFactory(getConnectionFactory());
  return redisTemplate;
 }
}

调整切面类NoRepeatSubmitAop.java

package com.common;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
/**
 * @功能描述 aop解析注解
 * @author www.gaozz.club
 * @date 2018-11-02
 */
public class NoRepeatSubmitAop {
 private Log logger = LogFactory.getLog(getClass());
 @Autowired
 private RedisTemplate template;
 @Around("execution(* com.example..*Controller.*(..)) && @annotation(nrs)")
 public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) {
  ValueOperations opsForValue = template.opsForValue();
  try {
   ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
   String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
   HttpServletRequest request = attributes.getRequest();
   String key = sessionId + "-" + request.getServletPath();
   if (opsForValue.get(key) == null) {// 如果缓存中有这个url视为重复提交
    Object o = pjp.proceed();
    opsForValue.set(key, 0, 2, TimeUnit.SECONDS);
    return o;
   } else {
    logger.error("重复提交");
    return null;
   }
  } catch (Throwable e) {
   e.printStackTrace();
   logger.error("验证重复提交时出现未知异常!");
   return "{\"code\":-889,\"message\":\"验证重复提交时出现未知异常!\"}";
  }
 }
}

关于怎么在spring boot中防止重复提交就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。


本文名称:怎么在springboot中防止重复提交
文章位置:http://azwzsj.com/article/pjiido.html