自定义注解实现拦截前端重复访问接口

本文介绍了一种使用AOP和自定义注解防止Web应用中重复提交请求的方法。通过在控制器方法上添加@NoRepeatSubmit注解,并结合AspectJ切面编程,实现对请求的唯一性和时效性控制,有效避免了短时间内多次提交相同请求的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 {

    /**
     * 设置请求锁定时间
     *
     * @return
     */
    long lockTime() default 1000;

2.AOP类 RepeatSubmitAspect

import com.agrhino.framework.common.response.Result;
import com.agrhino.framework.redis.util.RedisValueUtils;
import com.agrhino.miaomiao.auth.web.annotation.NoRepeatSubmit;
import com.agrhino.miaomiao.base.util.IPUtils;
import lombok.extern.slf4j.Slf4j;
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.beans.factory.annotation.Autowired;
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
@Slf4j
public class RepeatSubmitAspect {

    @Autowired
    private RedisValueUtils redisValueUtils;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointOut (NoRepeatSubmit noRepeatSubmit) {

    }

    @Around("pointOut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        long lockSeconds = noRepeatSubmit.lockTime();
        HttpServletRequest request = getRequest();
        // 此处可以用token或者JSessionId
        String token = request.getHeader("Access-Token");
        String path = request.getServletPath();
        String key = getKey(token, path);
        Object vlue = redisValueUtils.get(key);
        if (null==vlue) {
            // 执行进程
            Object o = pjp.proceed();
            redisValueUtils.set(key,key,lockSeconds,TimeUnit.MILLISECONDS);
            return o;

        } else {
            // 获取锁失败,认为是重复提交的请求
            log.warn("tryLock fail, key = [{}],ip =[{}]", key, IPUtils.getIp(request));
            return Result.failed("请稍后再试");
           // throw new ServiceException("重复提交");


        }

    }

    private String getKey(String token, String path) {
        return "NoRepeatSubmit:" + token + "-" + path;
    }

    private  HttpServletRequest getRequest() {
        ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return ra.getRequest();
    }

}

3.用例@NoRepeatSubmit(lockTime = 1000)

 @ApiOperation(value = "发布动态评论")
    @ApiImplicitParam(paramType = "header", name = "Access-Token", value = "accessToken", required = true)
    @PostMapping("createDynamicComment")
    @NoRepeatSubmit(lockTime = 1000)
    public Result<UserDynamicComment> addDynamicComment(@RequestBody @ApiParam(name = "form", value = "发布动态评论", required = true)
                                                     UserDynamicCommentForm form) {
        if(!inputFilterService.inputCheck(form.getComment())){
            return Result.failed("您的发言包含敏感信息,请修改后再发送");
        }
        UserDynamicComment userDynamicComment = new UserDynamicComment();
        BeanUtils.copyProperties(form, userDynamicComment);

        UserDynamicComment result = userDynamicCommentService.add(userDynamicComment);
        return Result.success(result);

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值