java实现方法重复调用防抖

防抖含义:在指定延时时间内,不管调用了多少次方法,只会执行最后一次调用的动作去执行方法。

举例:设定延时为5秒,调用防抖方法后,5秒内没有重复调用则会执行动作,5秒内有重复调用则会继续再延时等待五秒,直到5秒范围内没有调用再去执行方法。

1.核心工具类

package com.utils;

import java.util.Timer;
import java.util.TimerTask;


/**
 * 防抖
 *
 * @author 刘铁丝
 * @since 1.0
 */
public class DebounceTask {
    /**
     * 防抖实现关键类
     */
    private Timer timer;
    /**
     * 防抖时间:根据业务评估
     */
    private Long delay;
    /**
     * 开启线程执行任务
     */
    private Runnable runnable;

    public DebounceTask(Runnable runnable, Long delay) {
        this.runnable = runnable;
        this.delay = delay;
    }

    /**
     * @param runnable 要执行的任务
     * @param delay    执行时间
     * @return 初始化 DebounceTask 对象
     */
    public static DebounceTask build(Runnable runnable, Long delay) {
        return new DebounceTask(runnable, delay);
    }

    /**
     * Timer类执行:cancel()-->取消操作;schedule()-->执行操作
     */
    public void timerRun() {
        //如果有任务,则取消不执行(防抖实现的关键)
        if (timer != null) {
            timer.cancel();
        }
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //把 timer 设置为空,这样下次判断它就不会执行了
                timer = null;
                //执行 runnable 中的 run()方法
                runnable.run();
            }
        }, delay);
    }

}

2.调用方式

实现五秒内不管调用多少次debounceTask()方法 ,只会执行一次 System.out.println(">>> TODO something ");

	private static DebounceTask debounceTask = null;
	public void debounceTask() {
		if (debounceTask == null) {
		       debounceTask = DebounceTask.build(() -> {
		                System.out.println(">>> 防抖方法开始执行:" +  System.currentTimeMillis());
		                // TODO 
		                System.out.println(">>> TODO something ");
		            }, 5000L);
		}
       debounceTask.timerRun();
	}
<think>好的,我现在需要解决用户关于支付宝支付接口重复提交的问题。用户希望了解如何防止重复调用支付宝的支付接口。首先,我需要回顾一下相关的知识,尤其是之前提供的引用内容。 根据引用[3]和[4],常见的解决方案包括引入中间状态、加锁机制、超时处理以及幂等性设计。比如,支付订单可以设置一个“支付中”的状态,在发起支付前检查是否存在该状态的订单,如果有则阻止重复提交。此外,加锁可以确保同一时间只有一个请求处理支付,避免并发问题。超时处理则是在一定时间内未收到回调时主动查询结果,防止长时间挂起。幂等性保证即使多次收到同一请求,也只会处理一次。 接下来,我需要将这些思路应用到支付宝的具体场景中。支付宝的接口可能有自己的幂等性机制,比如订单号或交易号的唯一性校验。但作为服务端,仍需在业务层做防护,不能完全依赖第三方。 首先,用户在点击支付按钮时,前端应防止多次提交,但后端也需要做校验。所以,第一步是在创建支付订单时生成唯一的订单号,并在数据库中记录状态。当用户发起支付请求时,先检查该订单是否处于“支付中”或“已支付”状态,如果是则拒绝重复请求。 然后,需要考虑并发情况下的处理。比如,两个请求同时到达,如何避免同时处理。这时候需要用到分布式锁,例如基于Redis的锁,确保同一订单在同一时间只能有一个支付流程进行。 另外,支付宝的回调可能有延迟,所以需要设置超时机制。如果在设定的时间内未收到回调,比如30秒,系统应主动查询支付宝的支付状态,并根据结果更新订单状态。这可以避免订单一直处于中间状态,导致用户重复支付。 幂等性方面,支付宝的回调接口和主动查询接口都需要保证即使多次调用也不会重复处理。可以在处理支付结果时,先检查订单的当前状态,如果已经是最终状态(成功或失败),则不再处理。 还需要考虑网络问题导致的重试。客户端可能在支付过程中遇到网络中断,再次发起支付请求。此时,服务端应返回已有的支付信息,而不是创建新订单。 最后,结合支付宝的文档,查看是否有特定的参数或接口支持防止重复支付,比如`out_trade_no`的唯一性。确保每次支付请求使用唯一的订单号,并且支付宝端会拒绝重复的订单号。 总结起来,解决方案应包括:唯一订单号、状态检查、分布式锁、超时主动查询、回调幂等性处理,以及结合支付宝的接口特性进行适配。需要分步骤实现这些机制,确保各环节都能有效防止重复提交。</think>针对支付宝支付接口防止重复提交的问题,可通过以下分层方案实现交易安全,结合支付宝接口特性和系统设计优化: ### 一、基础防护层:订单状态控制 1. **引入中间状态** - 创建支付订单时设置状态为`待支付`; - 发起支付请求前,**将状态更新为`支付中`并加锁**,若检测到已有`支付中`状态则直接返回错误提示: ```sql UPDATE orders SET status = '支付中' WHERE order_id = 'xxx' AND status = '待支付'; ``` - 支付宝回调成功后更新为`已支付`,失败则回退为`待支付`[^3][^4]。 2. **唯一订单号约束** - 使用业务主键(如`order_id`)作为支付宝接口参数`out_trade_no`,支付宝会对重复的`out_trade_no`返回`ACQ.TRADE_HAS_SUCCESS`错误[^1]。 --- ### 二、并发控制层:分布式锁机制 1. **支付请求预锁定** ```java // 伪代码示例:基于Redis的分布式锁 String lockKey = "pay_lock:" + orderId; if (redis.setnx(lockKey, "1", 30s)) { try { // 执行支付逻辑 } finally { redis.del(lockKey); } } else { throw new RepeatSubmitException("订单支付处理中,请勿重复提交"); } ``` 2. **前端防抖与加载状态** - 按钮点击后禁用并显示加载动画,直到获得支付结果或超时[^2]。 --- ### 三、异步补偿层:超时主动查询 1. **定时任务兜底查询** - 支付中心设置**阶梯式主动查询**(如10s/20s/30s),超时后调用支付宝`alipay.trade.query`接口: ```python def check_payment_status(out_trade_no): response = alipay.trade_query(out_trade_no=out_trade_no) if response.code == "10000": update_order_status(response.trade_status) ``` - 超过最大重试次数(如3次)则标记为`支付失败`。 --- ### 四、幂等性保障层 1. **回调接口幂等设计** ```java @Transactional public void handleAlipayCallback(String outTradeNo) { Order order = orderDao.findByOutTradeNo(outTradeNo); if (order.getStatus().equals("已支付")) { return; // 直接忽略已处理的通知 } // 更新订单状态并记录支付时间 } ``` 2. **数据库唯一索引** - 对支付流水表的`out_trade_no`字段添加唯一索引,防止重复入库。 --- ### 五、支付宝特性适配 1. **预授权令牌(可选)** - 使用支付宝的`auth_token`实现预授权冻结资金,正式支付时通过`alipay.trade.pay`完成扣款,减少重复支付风险。 2. **同步返回+异步通知组合校验** - **不依赖同步返回结果**,必须以异步通知(`notify_url`)或主动查询作为最终支付结果依据[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值