当前位置: 首页 > news >正文

SpringBoot拦截器防重复提交实战

springboot防重复提交实现

    • 自定义注解
    • 拦截器逻辑
    • 配置拦截器
    • 抛异常代码
  • 开发中可能会经常遇到短时间内由于用户的重复点击导致几秒之内重复的请求,可能就是在这几秒之内由于各种问题,比如 网络 ,事务的隔离性等等问题导致了数据的重复等问题,因此在日常开发中必须规
    避这类的重复请求操作,今天就用拦截器处理一下这个问题

自定义注解

packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public@interfaceRepeatSubmit{/** * 默认失效时间时间(秒),小于或等于0表示不启用 */longseconds()default5;}

拦截器逻辑

packagetest;importcom.ruoyi.common.exception.RepeatSubmitException;importcom.sun.org.apache.xpath.internal.operations.Bool;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.core.annotation.AnnotationUtils;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Component;importorg.springframework.util.StringUtils;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.util.Objects;importjava.util.concurrent.TimeUnit;/** * 重复请求的拦截器 * * @Component:注解将当前类注入到IOC容器中 */@ComponentpublicclassRepeatSubmitInterceptorimplementsHandlerInterceptor{@AutowiredprivateStringRedisTemplatestringRedisTemplate;@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{if(handlerinstanceofHandlerMethod){//只拦截@RepeatSubmit注解HandlerMethodmethod=(HandlerMethod)handler;//标注在方法上的注解RepeatSubmitrepeatSubmitByMethod=AnnotationUtils.findAnnotation(method.getMethod(),RepeatSubmit.class);//标注在类上的注解RepeatSubmitrepeatSubmitByCls=AnnotationUtils.findAnnotation(method.getMethod().getDeclaringClass(),RepeatSubmit.class);//组合判断条件,根据自己项目实际需求来,这里只用简单的身份标识做拦截示例//没有限制重复提交,直接跳过if(Objects.isNull(repeatSubmitByMethod)&&Objects.isNull(repeatSubmitByCls))returntrue;//优先使用方法级注解,其次使用类级注解RepeatSubmitrepeatSubmit=Objects.nonNull(repeatSubmitByMethod)?repeatSubmitByMethod:repeatSubmitByCls;//验证注解配置的有效性:失效时间必须大于0if(repeatSubmit.seconds()<=0){returntrue;}//请求urlStringuri=request.getRequestURI();//构建更精确的Redis Key:结合用户标识防止不同用户间误判StringuserKey=getUserIdentifier(request);StringredisKey=userKey+":"+uri;//redis中存在返回false,不存在返回trueBooleanifAbsent=stringRedisTemplate.opsForValue().setIfAbsent(redisKey,"1",Objects.nonNull(repeatSubmitByMethod)?repeatSubmitByMethod.seconds():repeatSubmitByCls.seconds(),TimeUnit.SECONDS);//如果存在,表示已经请求过了,直接抛出异常,由全局异常进行处理返回指定信息if(ifAbsent!=null&&!ifAbsent){thrownewRepeatSubmitException();}returntrue;}returnHandlerInterceptor.super.preHandle(request,response,handler);}/** * 获取用户唯一标识 * 优先级:Token > SessionId > IP地址 */privateStringgetUserIdentifier(HttpServletRequestrequest){//尝试从请求头获取TokenStringtoken=request.getHeader("Authorization");if(StringUtils.hasText(token)){returntoken;}//尝试获取SessionIdStringsessionId=request.getRequestedSessionId();if(StringUtils.hasText(sessionId)){returnsessionId;}//使用IP地址作为兜底方案Stringip=getClientIp(request);returnStringUtils.hasText(ip)?ip:"unknown";}/** * 获取客户端真实IP */privateStringgetClientIp(HttpServletRequestrequest){Stringip=request.getHeader("X-Forwarded-For");if(StringUtils.hasText(ip)&&!"unknown".equalsIgnoreCase(ip)){//多次反向代理后会有多个IP值,第一个为真实IPintindex=ip.indexOf(',');if(index!=-1){returnip.substring(0,index);}returnip;}ip=request.getHeader("X-Real-IP");if(StringUtils.hasText(ip)&&!"unknown".equalsIgnoreCase(ip)){returnip;}ip=request.getHeader("Proxy-Client-IP");if(StringUtils.hasText(ip)&&!"unknown".equalsIgnoreCase(ip)){returnip;}ip=request.getHeader("WL-Proxy-Client-IP");if(StringUtils.hasText(ip)&&!"unknown".equalsIgnoreCase(ip)){returnip;}returnrequest.getRemoteAddr();}}

配置拦截器

packagetest;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;publicclassWebConfigimplementsWebMvcConfigurer{@AutowiredprivateRepeatSubmitInterceptorrepeatSubmitInterceptor;@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){finalString[]commonExclude={"/error","/files/**"};registry.addInterceptor(repeatSubmitInterceptor).excludePathPatterns(commonExclude);}}

抛异常代码

packagecom.ruoyi.common.exception;/** * 重复提交异常 * * @author ruoyi */publicclassRepeatSubmitExceptionextendsRuntimeException{privatestaticfinallongserialVersionUID=1L;/** * 错误提示 */privateStringmessage;/** * 空构造方法 */publicRepeatSubmitException(){this("不允许重复提交,请稍后再试");}publicRepeatSubmitException(Stringmessage){super(message);this.message=message;}@OverridepublicStringgetMessage(){returnmessage;}publicRepeatSubmitExceptionsetMessage(Stringmessage){this.message=message;returnthis;}}
http://www.zskr.cn/news/1465818.html

相关文章:

  • 告别手动配置:用Netplan和systemd-resolved在Debian10上优雅管理网络与DNS
  • 2026舟山市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 2026杭州室内游玩乐园畅玩攻略|告别酷暑阴雨一站式解锁未来城市乐园 - 资讯速览
  • 二〇二六年石家庄六家正规黄金回收机构实测:权威背书下的口碑门店深度测评 - 薛定谔的梨花猫
  • MATLAB写的五子棋单机版,带鼠标下棋、悔棋和自动胜负判断
  • 运放选型避坑指南:除了GBW和压摆率,稳定性参数(相位裕度)你关注了吗?
  • Zynq PL-PS交互实战:用AXI GPIO中断实现按键控制LED(附完整SDK代码与调试技巧)
  • 微信怎么发起活动报名?云众评选全流程教程 - 微信投票小程序
  • 营口市外网管道漏水检测、消防、供暖、自来水、埋地管道测漏、精准定位 抢修 - 天堂海洋
  • 破解山洪防御难题,从GIS水文分析到HEC-RAS建模:山洪径流模拟与危险性评价全流程实战指南
  • 项目不同阶段怎么用Claude Code?一份来自真实项目的使用手册
  • 苏州工业机器人培训选购指南:如何选到适合自己的课程 - 资讯纵览
  • 齐齐哈尔哪里有 CPPM 正规报考机构 - 中供国培
  • 鼓楼区马桶堵塞、厨房下水慢、菜池反水、地漏不通、专业疏通厕所下水管道师傅 - 天堂海洋
  • 保姆级教程:用ESP_DOWNLOAD_TOOL给ESP8266-01S烧录AT固件,附完整接线图与常见乱码解决方案
  • 在职备考PMP高效攻略|零基础上班族3个月碎片化通关学习方案
  • 西安市上门校准维修跳数地磅,旧磅升级搬迁,无人值守项目安装 - 天堂海洋
  • ★大润发购物卡回收,陈姐被骗后终于醒悟! - 京顺回收
  • 2026年最新深圳市黄金回收白银回收铂金回收彩金回收TOP5靠谱门店甄选 识店+辨价+安全交易指南及联系方式推荐 - 前途无量YY
  • Qt6从入门到实战:一份给嵌入式开发者的保姆级学习路线图(含避坑指南)
  • 朔州市黄金回收白银回收铂金回收彩金回收门店优选+2026年最新黄金回收TOP5排行榜靠谱商家推荐及联系方式 - 亦辰小黄鸭
  • 2026年最新十堰市黄金回收白银回收铂金回收彩金回收TOP5靠谱门店甄选 识店+辨价+安全交易指南及联系方式推荐 - 前途无量YY
  • 襄阳市黄金回收白银回收铂金回收彩金回收门店优选+2026年最新黄金回收TOP5排行榜靠谱商家推荐及联系方式 - 亦辰小黄鸭
  • 松原市黄金回收白银回收铂金回收彩金回收门店优选+2026年最新黄金回收TOP5排行榜靠谱商家推荐及联系方式 - 亦辰小黄鸭
  • Oracle ebs 设计的这套 8 段式 COA(会计科目表)结构非常经典,它融合了 Oracle EBS 的通用实践与 SAP 的管控思想
  • 2026年最新朔州市黄金回收白银回收铂金回收彩金回收TOP5靠谱门店甄选 识店+辨价+安全交易指南及联系方式推荐 - 前途无量YY
  • 黑色极简风电影门户HTML5源码包,含首页/详情页/登录注册五页完整结构
  • 2026年6月上海手表回收行业深度解读——六大平台核心优势解析 - 薛定谔的梨花猫
  • 基于随机森林的二手房数据分析与预测系统
  • 2026年最新四平市黄金回收白银回收铂金回收彩金回收TOP5靠谱门店甄选 识店+辨价+安全交易指南及联系方式推荐 - 前途无量YY