springboot冪等切片的實(shí)現(xiàn)
一、前言
最近測(cè)試提某些接口重復(fù)提交的問題,想了下應(yīng)該不止是前端點(diǎn)擊之后按鈕不可點(diǎn)擊的問題,后端應(yīng)該根據(jù)登錄token、操作方法、參數(shù)做多層的判斷。
二、示例
切片代碼
/**
?* 接口冪等切面
?* @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;
? ? ? ? //短時(shí)間內(nèi)沒進(jìn)行相似操作
? ? ? ? if(redisUtil.hasKey(idempotentKey)){
? ? ? ? ? ? //接口參數(shù)是否一致
? ? ? ? ? ? String idempotentValue = redisUtil.getCacheObject(idempotentKey);
? ? ? ? ? ? log.info("idempotentValue : {}",idempotentValue);
? ? ? ? ? ? if(args.equals(idempotentValue)){
? ? ? ? ? ? ? ? throw new BusinessException("請(qǐng)勿重復(fù)操作");
? ? ? ? ? ? }
? ? ? ? } else{
? ? ? ? ? ? //30s內(nèi)禁止重復(fù)操作
? ? ? ? ? ? redisUtil.setCacheObject(idempotentKey,args,30, TimeUnit.SECONDS);
? ? ? ? }
? ? }
}用到一個(gè)redisutil
@Component
public class RedisUtil {
? ? @Resource
? ? public RedisTemplate redisTemplate;
? ? /**
? ? ?* 緩存基本的對(duì)象,Integer、String、實(shí)體類等
? ? ?*
? ? ?* @param key 緩存的鍵值
? ? ?* @param value 緩存的值
? ? ?*/
? ? public <T> void setCacheObject(final String key, final T value)
? ? {
? ? ? ? redisTemplate.opsForValue().set(key, value);
? ? }
? ? /**
? ? ?* 緩存基本的對(duì)象,Integer、String、實(shí)體類等
? ? ?*
? ? ?* @param key 緩存的鍵值
? ? ?* @param value 緩存的值
? ? ?* @param timeout 時(shí)間
? ? ?* @param timeUnit 時(shí)間顆粒度
? ? ?*/
? ? public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
? ? {
? ? ? ? redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
? ? }
? ? /**
? ? ?* 設(shè)置有效時(shí)間
? ? ?*
? ? ?* @param key Redis鍵
? ? ?* @param timeout 超時(shí)時(shí)間
? ? ?* @return true=設(shè)置成功;false=設(shè)置失敗
? ? ?*/
? ? public boolean expire(final String key, final long timeout)
? ? {
? ? ? ? return expire(key, timeout, TimeUnit.SECONDS);
? ? }
? ? /**
? ? ?* 設(shè)置有效時(shí)間
? ? ?*
? ? ?* @param key Redis鍵
? ? ?* @param timeout 超時(shí)時(shí)間
? ? ?* @param unit 時(shí)間單位
? ? ?* @return true=設(shè)置成功;false=設(shè)置失敗
? ? ?*/
? ? public boolean expire(final String key, final long timeout, final TimeUnit unit)
? ? {
? ? ? ? return redisTemplate.expire(key, timeout, unit);
? ? }
? ? /**
? ? ?* 獲得緩存的基本對(duì)象。
? ? ?*
? ? ?* @param key 緩存鍵值
? ? ?* @return 緩存鍵值對(duì)應(yīng)的數(shù)據(jù)
? ? ?*/
? ? public <T> T getCacheObject(final String key)
? ? {
? ? ? ? ValueOperations<String, T> operation = redisTemplate.opsForValue();
? ? ? ? return operation.get(key);
? ? }
? ? /**
? ? ?* 刪除單個(gè)對(duì)象
? ? ?*
? ? ?* @param key
? ? ?*/
? ? public boolean deleteObject(final String key)
? ? {
? ? ? ? return redisTemplate.delete(key);
? ? }
? ? /**
? ? ?* 刪除集合對(duì)象
? ? ?*
? ? ?* @param collection 多個(gè)對(duì)象
? ? ?* @return
? ? ?*/
? ? public long deleteObject(final Collection collection)
? ? {
? ? ? ? return redisTemplate.delete(collection);
? ? }
? ? /**
? ? ?* 緩存List數(shù)據(jù)
? ? ?*
? ? ?* @param key 緩存的鍵值
? ? ?* @param dataList 待緩存的List數(shù)據(jù)
? ? ?* @return 緩存的對(duì)象
? ? ?*/
? ? public <T> long setCacheList(final String key, final List<T> dataList)
? ? {
? ? ? ? Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
? ? ? ? return count == null ? 0 : count;
? ? }
? ? /**
? ? ?* 獲得緩存的list對(duì)象
? ? ?*
? ? ?* @param key 緩存的鍵值
? ? ?* @return 緩存鍵值對(duì)應(yīng)的數(shù)據(jù)
? ? ?*/
? ? public <T> List<T> getCacheList(final String key)
? ? {
? ? ? ? return redisTemplate.opsForList().range(key, 0, -1);
? ? }
? ? /**
? ? ?* 緩存Set
? ? ?*
? ? ?* @param key 緩存鍵值
? ? ?* @param dataSet 緩存的數(shù)據(jù)
? ? ?* @return 緩存數(shù)據(jù)的對(duì)象
? ? ?*/
? ? 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中存入數(shù)據(jù)
? ? ?*
? ? ?* @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中的數(shù)據(jù)
? ? ?*
? ? ?* @param key Redis鍵
? ? ?* @param hKey Hash鍵
? ? ?* @return Hash中的對(duì)象
? ? ?*/
? ? public <T> T getCacheMapValue(final String key, final String hKey)
? ? {
? ? ? ? HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
? ? ? ? return opsForHash.get(key, hKey);
? ? }
? ? /**
? ? ?* 獲取多個(gè)Hash中的數(shù)據(jù)
? ? ?*
? ? ?* @param key Redis鍵
? ? ?* @param hKeys Hash鍵集合
? ? ?* @return Hash對(duì)象集合
? ? ?*/
? ? public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
? ? {
? ? ? ? return redisTemplate.opsForHash().multiGet(key, hKeys);
? ? }
? ? /**
? ? ?* 獲得緩存的基本對(duì)象列表
? ? ?*
? ? ?* @param pattern 字符串前綴
? ? ?* @return 對(duì)象列表
? ? ?*/
? ? 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);
? ? }
}到此這篇關(guān)于springboot冪等切片的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)springboot冪等切片內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java9新特性對(duì)HTTP2協(xié)議支持與非阻塞HTTP?API
這篇文章主要為大家介紹了Java9新特性對(duì)HTTP2協(xié)議的支持與非阻塞HTTP?API,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03
Spring Boot Shiro在Web應(yīng)用中的作用詳解
這篇文章主要為大家介紹了Spring Boot Shiro在Web應(yīng)用中的作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Java圖片與二進(jìn)制相互轉(zhuǎn)換實(shí)現(xiàn)示例講解
這篇文章主要介紹了Java圖片與二進(jìn)制相互轉(zhuǎn)換實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
Java大數(shù)據(jù)開發(fā)Hadoop?MapReduce
MapReduce的思想核心是“分而治之”,適用于大量復(fù)雜的任務(wù)處理場(chǎng)景(大規(guī)模數(shù)據(jù)處理場(chǎng)景)Map負(fù)責(zé)“分”,即把復(fù)雜的任務(wù)分解為若干個(gè)“簡(jiǎn)單的任務(wù)”來并行處理??梢赃M(jìn)行拆分的前提是這些小任務(wù)可以并行計(jì)算,彼此間幾乎沒有依賴關(guān)系2023-03-03
idea使用Maven Helper插件去掉無用的poom 依賴信息(詳細(xì)步驟)
這篇文章主要介紹了idea使用Maven Helper插件去掉無用的poom 依賴信息,本文分步驟給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04

