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

 更新时间:2023年09月03日 15:26:06   作者:草帽夫卡  
基于SpringBoot框架来开发业务后台项目时,接口重复提交是一个常见的问题,本文主要介绍了SpringBoot拦截器实现项目防止接口重复提交,具有一定的参考价值,感兴趣的可以了解一下

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

  • 首先,我们需要引入一个Aop依赖。在pom.xml文件中添加如下依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  • 创建一个自定义注解@NoRepeatSubmit,用于标记需要拦截的接口:
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;
}
  • 创建一个拦截器类NoRepeatSubmitInterceptor,实现HandlerInterceptor接口,并在其中实现拦截逻辑:
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");
    }
}
  • 在需要进行拦截的接口上添加@NoRepeatSubmit注解,例如:
@RestController
public class UserController {
    @NoRepeatSubmit // 添加此注解表示该接口需要拦截重复提交请求
    @GetMapping("/submit")
    public String submit() {
        // 处理业务逻辑...
        return "success";
    }
}

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

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

相关文章

  • J2SE 1.5版本的新特性一览

    J2SE 1.5版本的新特性一览

    J2SE 1.5版本的新特性一览...
    2006-12-12
  • Jersey实现Restful服务(实例讲解)

    Jersey实现Restful服务(实例讲解)

    下面小编就为大家带来一篇Jersey实现Restful服务(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java计算代码段执行时间的详细代码

    java计算代码段执行时间的详细代码

    java里计算代码段执行时间可以有两种方法,一种是毫秒级别的计算,另一种是更精确的纳秒级别的计算,这篇文章主要介绍了java计算代码段执行时间,需要的朋友可以参考下
    2022-08-08
  • Javabean基于xstream包实现转XML文档的方法

    Javabean基于xstream包实现转XML文档的方法

    这篇文章主要介绍了Javabean基于xstream包实现转XML文档的方法,结合具体实例形式分析了xstream包用于转换xml文件的具体使用技巧,需要的朋友可以参考下
    2017-05-05
  • 面试突击之跨域问题的解决方案详解

    面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看
    2022-09-09
  • VsCode配置java环境的详细图文教程

    VsCode配置java环境的详细图文教程

    vscode是一个免费的代码编辑器,支持多种主题,应用起来简单方便,下面这篇文章主要给大家介绍了关于VsCode配置java环境的详细图文教程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Java代码为例讲解堆的性质和基本操作以及排序方法

    Java代码为例讲解堆的性质和基本操作以及排序方法

    堆数据结构可以看作一颗完全二叉树,因而又被成为二叉堆,这里我们以Java代码为例讲解堆的性质和基本操作以及排序方法,需要的朋友可以参考下
    2016-06-06
  • Java Swing GridBagLayout网格袋布局的实现

    Java Swing GridBagLayout网格袋布局的实现

    这篇文章主要介绍了Java Swing GridBagLayout网格袋布局的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • spring @Lazy延迟注入的逻辑实现

    spring @Lazy延迟注入的逻辑实现

    有时候我们会在属性注入的时候添加@Lazy注解实现延迟注入,今天咱们通过阅读源码来分析下原因,感兴趣的可以了解一下
    2021-08-08
  • 解决javac不是内部或外部命令,也不是可运行程序的报错问题

    解决javac不是内部或外部命令,也不是可运行程序的报错问题

    在学着使用Java的命令行来编译java文件的时候,遇到了这个问题,本文主要介绍了解决javac不是内部或外部命令,也不是可运行程序的报错问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论