最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Redisson實(shí)現(xiàn)防重復(fù)提交

2022-05-06 18:23 作者:匯智知了堂  | 我要投稿

防止重復(fù)提交的重要性?

在業(yè)務(wù)開(kāi)發(fā)當(dāng)中,為什么我們要去想辦法解決重復(fù)提交這一問(wèn)題的發(fā)生呢?網(wǎng)上的概念有很多:導(dǎo)致表 單重復(fù)提交的,造成數(shù)據(jù)重復(fù)的,增加服務(wù)器負(fù)載的,甚至?xí)斐煞?wù)器宕機(jī)的,那么為什么會(huì)出現(xiàn)這 種情況呢?頁(yè)面快速的操作以及網(wǎng)絡(luò)Io問(wèn)題或者數(shù)據(jù)庫(kù)響應(yīng)慢,這些都會(huì)增加后端重復(fù)處理的概率, 就拿之前做的項(xiàng)目來(lái)說(shuō),因?yàn)闃I(yè)務(wù)性較強(qiáng),需要進(jìn)行一個(gè)"點(diǎn)贊"的操作,寫(xiě)好業(yè)務(wù)以后在測(cè)試時(shí)連續(xù)點(diǎn) 擊幾下,重復(fù)地進(jìn)行點(diǎn)贊和取消點(diǎn)贊操作,因?yàn)椴僮鬟^(guò)于頻繁,而服務(wù)器走過(guò)來(lái)的響應(yīng)速度沒(méi)有那么快 地進(jìn)行處理,就會(huì)導(dǎo)致數(shù)據(jù)的重復(fù)插入情況,最后導(dǎo)致服務(wù)器報(bào)錯(cuò),這時(shí),防止重復(fù)提交就顯得很重要 了。

如何防重復(fù)提交?

實(shí)現(xiàn)方法有非常多,但是原理大概都是相通的,我選擇的是通過(guò)使用AOP切面+Redisson來(lái)進(jìn)行處理, 前端發(fā)起請(qǐng)求的時(shí)候需要在請(qǐng)求頭里將token給我,然后我這邊通過(guò)token+ip再加上請(qǐng)求的路徑作為一 個(gè)key存到redis里面去,設(shè)置一個(gè)過(guò)期時(shí)間,下一次再?gòu)木彺娈?dāng)中讀取和當(dāng)前時(shí)間進(jìn)行一個(gè)判斷,若大 于我們自己設(shè)定的超時(shí)時(shí)間,就進(jìn)行攔截,不讓它進(jìn)行后面的業(yè)務(wù)代碼,并給出提示“操作頻繁,請(qǐng)稍 后重試” 分布式鎖方案采用Redisson,這也是官網(wǎng)比較推薦的使用方法。利用分布式鎖的特性來(lái)防止重復(fù)提交。

1.導(dǎo)入依賴(lài)

????<dependency>?

????<groupId>org.redisson</groupId>

???? <artifactId>redisson-spring-boot-starter</artifactId>?

????<version>3.15.0</version>?

????</dependency>

2.使用注解

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)?

@Documented?

public @interface NoRepeat {?

/**

* 鎖名稱(chēng)

*/?

String lockName() default "no-repeat-default-lock-";?

/**

* 參數(shù)key,支持Spel?

*/

String key() default "";

/**

* 獲取鎖的最長(zhǎng)時(shí)間,單位默認(rèn)為秒?

*/?

long waitTime() default 5;

/**

* 租賃時(shí)間,單位默認(rèn)為秒

* 加鎖的時(shí)間。超過(guò)這個(gè)時(shí)間后鎖便自動(dòng)解開(kāi)了?

*/

3.編寫(xiě)切面?

????@Slf4j?

????@Aspect?

????@Component?

????public class SystemAspect {?

????@Resource private RedissonClient redissonClient;?

????/**

????* SPEL表達(dá)式解析器?

????*/?

????private final SpelExpressionParser parser = new SpelExpressionParser();?

????LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); @Around(value = "@annotation(NoRepeat)")?

????public Object doNoRepeatAround(ProceedingJoinPoint pjp) throws InterruptedException?

????{?

????NoRepeat noRepeat = CsUtil.getJoinPointAnnotation(pjp, NoRepeat.class);?

????String key = parseKey(pjp, noRepeat);?

????RLock fairLock = redissonClient.getFairLock(noRepeat.lockName() + key);?

????boolean res = fairLock.tryLock(noRepeat.waitTime(), noRepeat.leaseTime(), TimeUnit.SECONDS);?

????if (res) {?

????log.info("拿到鎖");

???? try {return pjp.proceed();?

????} catch (Throwable e) {?

????log.error(e.getMessage(), e);?

????throw new ServiceException(e.getMessage());?

????} finally { fairLock.unlock(); log.info("釋放鎖操作"); }

???? } else { log.error("重復(fù)的請(qǐng)求");?

????return new Response<Boolean>(999, "重復(fù)的請(qǐng)求");?

????????}?

????}

????private String parseKey(ProceedingJoinPoint pjp, NoRepeat noRepeat) {?

????Object[] args = pjp.getArgs();?

????Method method = ((MethodSignature) pjp.getSignature()).getMethod();?

????String[] params = discoverer.getParameterNames(method);?

????EvaluationContext context = new StandardEvaluationContext();?

????for (int len = 0; len < Objects.requireNonNull(params).length; len++) {?

????context.setVariable(params[len], args[len]); }

????String keySpel = noRepeat.key(); Expression keyExpression = parser.parseExpression(keySpel);

???? return keyExpression.getValue(context, String.class);?

????????}?

????}

4. 使用方式

????@RestController?

????public class TestController {?

????@ApiOperation("身份綁定(注冊(cè))接口")?

????@NoRepeat(key = "#user.name")?

????@PostMapping("/v1/test/noRepeat")?

????public Response<User> doSome(@RequestBody User user) {

???? return new Response<>();?

????}

????@Data?

????static class User {?

????private String name;

???? ????}

???? }

5.展示效果


Redisson實(shí)現(xiàn)防重復(fù)提交的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
丰原市| 武乡县| 会同县| 濮阳市| 乌兰县| 恩施市| 揭西县| 元阳县| 杭锦旗| 理塘县| 涡阳县| 喀喇沁旗| 南木林县| 景泰县| 红河县| 禹城市| 绍兴市| 封丘县| 铁力市| 天台县| 武冈市| 金寨县| 盐亭县| 金溪县| 余江县| 洛宁县| 蚌埠市| 昌邑市| 长沙县| 平泉县| 芦山县| 凤阳县| 五大连池市| 竹溪县| 迁西县| 湘潭市| 武威市| 广德县| 岳西县| 扎兰屯市| 静海县|