springboot冪等切片的實(shí)現(xiàn)
一、前言
最近測試提某些接口重復(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-03Spring Boot Shiro在Web應(yīng)用中的作用詳解
這篇文章主要為大家介紹了Spring Boot Shiro在Web應(yīng)用中的作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Java圖片與二進(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-03Java大數(shù)據(jù)開發(fā)Hadoop?MapReduce
MapReduce的思想核心是“分而治之”,適用于大量復(fù)雜的任務(wù)處理場景(大規(guī)模數(shù)據(jù)處理場景)Map負(fù)責(zé)“分”,即把復(fù)雜的任務(wù)分解為若干個(gè)“簡單的任務(wù)”來并行處理??梢赃M(jìn)行拆分的前提是這些小任務(wù)可以并行計(jì)算,彼此間幾乎沒有依賴關(guān)系2023-03-03idea使用Maven Helper插件去掉無用的poom 依賴信息(詳細(xì)步驟)
這篇文章主要介紹了idea使用Maven Helper插件去掉無用的poom 依賴信息,本文分步驟給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04