java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot 防止接口重复提交

SpringBoot拦截器实现项目防止接口重复提交

作者:草帽夫卡

基于SpringBoot框架来开发业务后台项目时,接口重复提交是一个常见的问题,本文主要介绍了SpringBoot拦截器实现项目防止接口重复提交,具有一定的参考价值,感兴趣的可以了解一下

基于SpringBoot框架来开发业务后台项目时,接口重复提交是一个常见的问题。为了避免这个问题,我们可以通过自定义拦截器实现一个后台拦截接口重复提交的功能,本文将介绍如何使用基于SpringBoot实现这个功能。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
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)
public @interface NoRepeatSubmit {
    /**
     * 设置请求锁定时间,默认为5秒
     */
    int lockTime() default 5;
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class NoRepeatSubmitInterceptor implements HandlerInterceptor {
    @Pointcut("@annotation(com.example.demo.annotation.NoRepeatSubmit)")
    public void noRepeatSubmitPointcut() {
    }
    @Around("noRepeatSubmitPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取请求参数中的token值
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpSession session = request.getSession();
        String token = session.getAttribute("token").toString();
        // 判断是否已经提交过请求,如果已经提交过并且时间间隔小于锁时间,则直接返回成功结果,否则认为是重复提交,抛出异常并锁定session
        if (isSubmitted(token)) {
            String lockKey = UUID.randomUUID().toString();
            session.setAttribute(lockKey, System.currentTimeMillis());
            throw new RuntimeException("请勿重复提交");
        } else {
            session.setAttribute("token", token);
            return joinPoint.proceed();
        }
    }
    private boolean isSubmitted(String token) {
        HttpSession session = request.getSession();
        Object lockKey = session.getAttribute(token);
        if (lockKey == null) {
            return false;
        } else {
            long lockTime = (Long) session.getAttribute(token);
            if (lockTime > 0 && System.currentTimeMillis() - lockTime < TimeUnit.SECONDS.toMillis(5)) {
                return true;
            } else {
                session.removeAttribute(token);
                return false;
            }
        }
    }
}

实现HandlerInterceptor接口的重写,重写preHandle、postHandle、afterCompletion方法。拦截器中的方法执行流程为 preHandle → controlle → postHandle → afterCompletion。然后需要将拦截器注册到容器中,可以通过实现WebMvcConfigurer的addInterceptors方法来实现。下面是一个简单的例子:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new NoRepeatSubmitInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/register");
    }
}
@RestController
public class UserController {
    @NoRepeatSubmit // 添加此注解表示该接口需要拦截重复提交请求
    @GetMapping("/submit")
    public String submit() {
        // 处理业务逻辑...
        return "success";
    }
}

通过以上步骤,我们实现了一个简单的后台拦截接口重复提交的功能。在实际项目中,还需要考虑更多的细节,例如如何保证锁的释放、如何处理并发请求等。但这个示例应该能帮助你入门SpringBoot拦截器的使用。

到此这篇关于SpringBoot拦截器实现项目防止接口重复提交的文章就介绍到这了,更多相关SpringBoot 防止接口重复提交内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文