0
点赞
收藏
分享

微信扫一扫

iMX6ULL 嵌入式linux开发 | 4G无线广播终端实现方案介绍

未定义变量 2024-05-26 阅读 10

在 Spring Boot 中,可以使用 AOP(面向切面编程)来防止重复提交。通过 AOP,可以在方法调用前后添加额外的逻辑,而不需要修改方法本身的代码。下面是一个基于 AOP 的解决方案:

使用 AOP 防止重复提交

步骤:

  1. 定义注解:创建一个自定义注解,用于标记需要防止重复提交的方法。
  2. 编写切面:使用 AOP 切面,在方法调用前检查重复提交的条件。

1. 定义注解

首先,创建一个自定义注解 @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 {
    // 可以定义属性以配置注解,例如设置过期时间等
}

2. 编写切面

然后,编写一个 AOP 切面类,在方法调用前检查请求是否重复提交。

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.StringRedisTemplate;
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 java.util.concurrent.TimeUnit;

@Aspect
@Component
public class NoRepeatSubmitAspect {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Around("@annotation(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint joinPoint, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        
        // 这里也可以从请求头里取Token,和前端商量好就行。
        String sessionId = request.getSession().getId();
        String uri = request.getRequestURI();
        String key = "no_repeat_submit:" + sessionId + ":" + uri;

        // 这里可以改为用一个分布式锁工具
        Boolean isAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, "locked", 5, TimeUnit.SECONDS);
        if (Boolean.TRUE.equals(isAbsent)) {
            try {
                return joinPoint.proceed();
            } finally {
                stringRedisTemplate.delete(key);
            }
        } else {
            throw new RuntimeException("重复提交");
        }
    }
}

3. 应用注解

在需要防止重复提交的方法上使用 @NoRepeatSubmit 注解。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class FormController {

    @NoRepeatSubmit
    @PostMapping("/submitForm")
    public String submitForm() {
        // 处理表单提交逻辑
        return "success";
    }
}

说明

  1. 注解 @NoRepeatSubmit:用于标记需要防止重复提交的方法。
  2. 切面 NoRepeatSubmitAspect:通过 Redis 锁机制来防止重复提交。在方法调用前,生成一个基于 session ID 和请求 URI 的唯一键,尝试获取 Redis 锁,如果获取成功则继续执行方法并在执行完成后释放锁;如果获取失败,则抛出重复提交异常。

注意事项

  1. Redis 配置:确保应用程序中已经配置了 Redis。
  2. 异常处理:可以通过全局异常处理器来捕获和处理重复提交异常。

这种方式适用于单节点和分布式部署的场景,因为 Redis 可以作为一个全局的锁服务,保证分布式环境下的唯一性。

举报

相关推荐

0 条评论