在傳統的web專案中,防止重複提交,通常做法是:後端生成乙個唯一的提交令牌(uuid),並儲存在服務端。頁面提交請求攜帶這個提交令牌,後端驗證並在第一次驗證後刪除該令牌,保證提交請求的唯一性。上述的思路其實沒有問題的,但是需要前後端都稍加改動,如果在業務開發完在加這個的話,改動量未免有些大了,本節的實現方案無需前端配合,純後端處理。
自定義註解 @norepeatsubmit 標記所有controller中的提交請求
通過aop 對所有標記了 @norepeatsubmit 的方法攔截
在業務方法執行前,獲取當前使用者的 token(或者jsessionid)+ 當前請求位址,作為乙個唯一 key,去獲取 redis
分布式鎖(如果此時併發獲取,只有乙個執行緒會成功獲取鎖)
業務方法執行後,釋放鎖
關於redis 分布式鎖
使用redis 是為了在負載均衡部署,如果是單機的部署的專案可以使用乙個執行緒安全的本地cache 替代 redis
code
@aspect
@component
public class repeatsubmitaspect
@around("pointcut()")
public object before(proceedingjoinpoint pjp) ], clientid = [{}]", key, clientid);
if (issuccess) ], clientid = [{}]", key, clientid);
// 獲取鎖成功, 執行程序
object result = pjp.proceed();
// 解鎖
redislock.releaselock(key, clientid);
logger.info("releaselock success, key = [{}], clientid = [{}]", key, clientid);
return result;
} else ]", key);
return new apiresult(200, "重複請求,請稍後再試", null);
}} catch (throwable throwable)
return new apiresult(500, "系統異常", null);
}private string getkey(string token, string path)
private string getclientid()
}
測試**如下,模擬十個請求併發同時提交
@component
private static final logger logger = logge***ctory.getlogger(runtest.class);
@autowired
private resttemplate resttemplate;
@override
system.out.println("執行多執行緒測試");
}
成功防止重複提交,控制台日誌如下,可以看到十個執行緒的啟動時間幾乎同時發起,只有乙個請求提交成功了 Springboot如何使用AOP
切面的包 1 springboot 不自帶aop 需要自己新增依賴 org.springframework.bootgroupid spring boot starter aopartifactid dependency 2 直接 aspect寫切面類就行了1 連線點 可以理解為需要被增強的方法 2...
Spring Boot 之優雅使用 AOP
aop為aspect oriented programming的縮寫,意思是面向切面程式設計,通過預編譯的方式和執行時動態 實現程式功能的統一維護的一種技術。利用aop可以對業務邏輯進行分離,降低耦合度,提高可重用性,提高開發效率。主要用途 日誌記錄 事務處理 異常處理 安全處理 效能統計 在spr...
Springboot 中AOP的使用
面向切面程式設計 aspect oriented programming 是軟體程式設計思想發展到一定階段的產物,是物件導向程式設計的有益補充。aop一般適用於具有橫切邏輯的場合,如訪問控制 事務管理 效能檢測等。日誌 異常處理 事務控制等都是乙個健壯的業務系統所必須的。但是為了保證系統健壯可用,就...