溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot冪等切片怎么實現

發布時間:2022-03-01 16:27:13 來源:億速云 閱讀:168 作者:iii 欄目:開發技術

本篇內容介紹了“springboot冪等切片怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

一、前言

最近測試提某些接口重復提交的問題,想了下應該不止是前端點擊之后按鈕不可點擊的問題,后端應該根據登錄token、操作方法、參數做多層的判斷。

二、示例

切片代碼

/**
 * 接口冪等切面
 * @author Administrator
 */
@Slf4j
@Aspect
@Component
public class ApiIdempotentAspect {

    @Resource
    RedisUtil redisUtil;
    @Resource
    UserUtils userUtils;


    @Pointcut("@annotation(com.xx.anno.ApiIdempotent)")
    private void pointCut() {
    }

    @Before("pointCut()")
    public void doPoint(JoinPoint joinPoint) {
        String action = joinPoint.getSignature().getDeclaringTypeName()
                .substring(joinPoint.getSignature().getDeclaringTypeName().lastIndexOf(".")+1)
                + "::" + joinPoint.getSignature().getName();
        String args = JSON.toJSONString(joinPoint.getArgs());
        String token = userUtils.getAuthToke().replace("-","")
                .replace("Bearer ","");
        String idempotentKey = "api::idempotent::"+token+"::"+action;
        //短時間內沒進行相似操作
        if(redisUtil.hasKey(idempotentKey)){
            //接口參數是否一致
            String idempotentValue = redisUtil.getCacheObject(idempotentKey);
            log.info("idempotentValue : {}",idempotentValue);
            if(args.equals(idempotentValue)){
                throw new BusinessException("請勿重復操作");
            }
        } else{
            //30s內禁止重復操作
            redisUtil.setCacheObject(idempotentKey,args,30, TimeUnit.SECONDS);
        }

    }

}

用到一個redisutil

@Component
public class RedisUtil {

    @Resource
    public RedisTemplate redisTemplate;

    /**
     * 緩存基本的對象,Integer、String、實體類等
     *
     * @param key 緩存的鍵值
     * @param value 緩存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 緩存基本的對象,Integer、String、實體類等
     *
     * @param key 緩存的鍵值
     * @param value 緩存的值
     * @param timeout 時間
     * @param timeUnit 時間顆粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 設置有效時間
     *
     * @param key Redis鍵
     * @param timeout 超時時間
     * @return true=設置成功;false=設置失敗
     */
    public boolean expire(final String key, final long timeout)
    {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 設置有效時間
     *
     * @param key Redis鍵
     * @param timeout 超時時間
     * @param unit 時間單位
     * @return true=設置成功;false=設置失敗
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 獲得緩存的基本對象。
     *
     * @param key 緩存鍵值
     * @return 緩存鍵值對應的數據
     */
    public <T> T getCacheObject(final String key)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 刪除單個對象
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
        return redisTemplate.delete(key);
    }

    /**
     * 刪除集合對象
     *
     * @param collection 多個對象
     * @return
     */
    public long deleteObject(final Collection collection)
    {
        return redisTemplate.delete(collection);
    }

    /**
     * 緩存List數據
     *
     * @param key 緩存的鍵值
     * @param dataList 待緩存的List數據
     * @return 緩存的對象
     */
    public <T> long setCacheList(final String key, final List<T> dataList)
    {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }

    /**
     * 獲得緩存的list對象
     *
     * @param key 緩存的鍵值
     * @return 緩存鍵值對應的數據
     */
    public <T> List<T> getCacheList(final String key)
    {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 緩存Set
     *
     * @param key 緩存鍵值
     * @param dataSet 緩存的數據
     * @return 緩存數據的對象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
    {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext())
        {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 獲得緩存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key)
    {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 緩存Map
     *
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
    {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    /**
     * 獲得緩存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key)
    {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 往Hash中存入數據
     *
     * @param key Redis鍵
     * @param hKey Hash鍵
     * @param value 值
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
    {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
     * 獲取Hash中的數據
     *
     * @param key Redis鍵
     * @param hKey Hash鍵
     * @return Hash中的對象
     */
    public <T> T getCacheMapValue(final String key, final String hKey)
    {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }

    /**
     * 獲取多個Hash中的數據
     *
     * @param key Redis鍵
     * @param hKeys Hash鍵集合
     * @return Hash對象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
    {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
     * 獲得緩存的基本對象列表
     *
     * @param pattern 字符串前綴
     * @return 對象列表
     */
    public Collection<String> keys(final String pattern)
    {
        return redisTemplate.keys(pattern);
    }

    /**
     * 判斷key是否還在
     * @param key
     * @return
     */
    public boolean hasKey(final String key){
        return redisTemplate.hasKey(key);
    }
}

“springboot冪等切片怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女