赞
踩
- <?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>

- <?xml version="1.0" encoding="UTF-8"?>
- <configuration>
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <pattern>%d[%F:%L][%p]:%m%n</pattern>
- </encoder>
- </appender>
- <root level="info">
- <appender-ref ref="STDOUT"/>
- </root>
- </configuration>
- 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);
- }
- }

- 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 {
- }

- 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秒
- }
- }

- 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 ("程序逻辑返回");
- }
-
- }

然后F5刷新查看效果
QQ图片20180914165017.png
- spring:
- redis:
- host: 192.168.1.92
- port: 6379
- password: 123456
- 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;
- }
-
- }

- 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\":\"验证重复提交时出现未知异常!\"}";
- }
-
- }
-
- }

https://github.com/gzz2017gzz/spring-boot2-example/tree/master/54-spring-boot-repeat-submit-single
作者:不知不怪
链接:https://www.jianshu.com/p/09c6b05b670a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。