溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-04-17 17:11:27 來源:億速云 閱讀:214 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關怎么在spring boot中防止重復提交,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.example</groupId>
 <artifactId>springboot-repeat-submit</artifactId>
 <version>1.0</version>
 <packaging>jar</packaging>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.4.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>
  <dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>24.0-jre</version>
  </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>
</project>

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<String, Integer> 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<String, Integer> 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
 <K, V> RedisTemplate<K, V> getRedisTemplate() {
  RedisTemplate<K, V> redisTemplate = new RedisTemplate<K, V>();
  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<String, Integer> template;
 @Around("execution(* com.example..*Controller.*(..)) && @annotation(nrs)")
 public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) {
  ValueOperations<String, Integer> 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中防止重復提交就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女