10.15 springboot 使用AOP實現防止接口重複提交

背景:之前自己寫了一個簡單的書寫文章小項目,測試的時候發現多次點擊添加文章按鈕系統會出現重複的文章,所以就想著用aop實現防止接口重複提交功能。

個人設計的思路:

  1. 自定義一個註解,添加了該註解的接口可以防止重複提交。
  2. 定義切面類,實現代理。
  3. 使用登錄的userId+文章標題作為key存入redis,設置有效期,當有請求調用接口時,到redis中查找相應的key,如果能找到,則說明重複提交,如果找不到,則執行文章插入操作。

具體代碼如下:

一. 導入aop依賴

<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-aop/<artifactid>
/<dependency>

二. 自定義註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ArticleReSubmit {
}

三. 定義切面類

切面類需要使用@Aspect和@Component這兩個註解做標註。

@Aspect
@Component
@Slf4j
public class ArticleAspect {
@Resource
private RedisUtil redisUtil;
@Value("${user.session.key}")
private String userSessionKey;
@Pointcut(value = "@annotation(com.mypage.annotation.ArticleReSubmit)")
public void annotationPointCut() {
}
@Around("annotationPointCut()")
public Object NoReSubmit(ProceedingJoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//獲取request
HttpServletRequest request = attributes.getRequest();
HttpSession session = request.getSession();
//從session中獲取登錄的user對象,如果為null,則要求重新登錄
Object sessionUser = session.getAttribute(userSessionKey);
if (sessionUser == null) {
return Response.FAIL("頁面超時,請重新登錄");
}
User user = (User) sessionUser;
Integer userId = user.getId();
//獲取接口的請求參數,如果時Article類型,則保存為Article對象,使用Article對象裡的title屬性
Object[] args = joinPoint.getArgs();
Article article = null;
for (Object object : args) {
if (object instanceof Article) {
article = (Article) object;
}
}
if (args == null) {
return Response.FAIL("請求參數錯誤");
}
//組裝redis key 從redis中獲取對應的值
String key = userId + "_" + article.getTitle();
Object flag = redisUtil.getStr(key);
//如果redis中不存在對應的值,則執行原有的代碼邏輯(插入文章操作)
if (flag == null) {

//redis設置key,value值為1
redisUtil.setStr(key, "1");
//設置有效期為5分鐘
redisUtil.strSetExpireSeconds(key, 5*60L);
try {
return joinPoint.proceed();
} catch (Throwable throwable) {
redisUtil.delStr(key);
return Response.FAIL("系統錯誤,請聯繫管理員!");
}
} else {
//如果redis中存在對應的值,則證明重複提交,返回對應的信息
log.info("{}:重複提交", key);
return Response.FAIL("重複提交");
}
}
}

四. 在想要防止重複提交的接口上添加註解

("/addArticle")
@ResponseBody
@ArticleReSubmit
public Response addArticle(Article article, HttpServletRequest request) {
User user = (User) request.getSession().getAttribute(userSessionKey);
return articleService.addArticle(article, user);
}

至此,我們的代碼就完成了。

如果您覺得我哪寫得不好,或者有什麼意見或建議,還請指出。

謝謝!


分享到:


相關文章: