国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

springboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】

這篇具有很好參考價(jià)值的文章主要介紹了springboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

思路:通過(guò)AOP攔截注解標(biāo)記的方法,在Redis中維護(hù)一個(gè)計(jì)數(shù)器來(lái)記錄接口訪問(wèn)的頻率,
并根據(jù)限流策略來(lái)判斷是否允許繼續(xù)處理請(qǐng)求。

另一篇:springboot 自定義注解 ,aop切面@Around; 為接口實(shí)現(xiàn)日志插入【強(qiáng)行喂飯版】

不多說(shuō),直接上代碼:

一:創(chuàng)建限流類型

/**
 * 限流類型
 * 
 */

public enum LimitType
{
    /**
     * 默認(rèn)策略全局限流
     */
    DEFAULT,

    /**
     * 根據(jù)請(qǐng)求者IP進(jìn)行限流
     */
    IP
}



二:創(chuàng)建注解

import 你上面限流類型的路徑.LimitType;

import java.lang.annotation.*;

/**
 * 限流注解
 * 
 */
// 注解的作用目標(biāo)為方法
@Target(ElementType.METHOD) 

// 注解在運(yùn)行時(shí)保留,編譯后的class文件中存在,在jvm運(yùn)行時(shí)保留,可以被反射調(diào)用
@Retention(RetentionPolicy.RUNTIME) 

// 指明修飾的注解,可以被例如javadoc此類的工具文檔化,只負(fù)責(zé)標(biāo)記,沒(méi)有成員取值
@Documented 
public @interface LimiterToShareApi{

    /**
     * 限流key
     */
    public String key() default "";

    /**
     * 限流時(shí)間,單位秒
     */
    public int time() default 60;

    /**
     * 限流次數(shù)
     */
    public int count() default 100;

    /**
     * 限流類型,默認(rèn)全局限流
     */
    public LimitType limitType() default LimitType.DEFAULT;
}



**三:編寫業(yè)務(wù)異常類 **

/**
 * 業(yè)務(wù)異常
 * 
 */
public final class ServiceException extends RuntimeException
{
	// 序列化的版本號(hào)的屬性
    private static final long serialVersionUID = 1L;

    /**
     * 錯(cuò)誤碼
     */
    private Integer code;

    /**
     * 錯(cuò)誤提示
     */
    private String message;

    /**
     * 空構(gòu)造方法,避免反序列化問(wèn)題
     */
    public ServiceException(){
    }

	 /**
     * 異常信息
     */
    public ServiceException(String message){
        this.message = message;
    }
    
}


四:實(shí)現(xiàn)aop切面攔截,限流邏輯處理

import 你上面限流類型的路徑.LimitType;
import 你上面業(yè)務(wù)異常的路徑.ServiceException;
import 你上面限流注解的路徑.LimiterToShareApi;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;

 
// 聲明這是一個(gè)切面類
@Aspect
// 表明該類是一個(gè)組件,將該類交給spring管理。
@Component
// 指定執(zhí)行順序,值越小,越先執(zhí)行。限流策略一般最先執(zhí)行。
@Order(1) 
public class LimiterToShareApiAspect {

	// 記錄日志的Logger對(duì)象
    private static final Logger log = LoggerFactory.getLogger(LimiterToShareApiAspect.class);

	// 操作Redis的RedisTemplate對(duì)象
    private RedisTemplate<Object, Object> redisTemplate;

	//在Redis中執(zhí)行Lua腳本的對(duì)象
    private RedisScript<Long> limitScript;

    @Autowired
    public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setLimitScript(RedisScript<Long> limitScript) {
        this.limitScript = limitScript;
    }

	// 這個(gè)注解作用及普及 見(jiàn)文章后面解析
    @Before("@annotation(limiter)")
    public void doBefore(JoinPoint point, LimiterToShareApi limiter) throws Throwable {
        
        // 根據(jù)業(yè)務(wù)需求,看看是否去數(shù)據(jù)庫(kù)查詢對(duì)應(yīng)的限流策略,還是直接使用注解傳遞的值
        // 這里演示為 獲取注解的值
        int time = limiter.time();
        int count = limiter.count();

        String combineKey = getCombineKey(limiter, point);
        List<Object> keys = Collections.singletonList(combineKey);
        try {
            Long number = redisTemplate.execute(limitScript, keys, count, time);
            if (number == null || number.intValue() > count) {
                throw new ServiceException("限流策略:訪問(wèn)過(guò)于頻繁,請(qǐng)稍候再試");
            }
            log.info("限制請(qǐng)求'{}',當(dāng)前請(qǐng)求'{}',緩存key'{}'", count, number.intValue(), combineKey);
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("服務(wù)器限流異常,請(qǐng)稍候再試");
        }
    }
    

    /**
     * 獲取用于限流的組合鍵,根據(jù)LimterToShareApi注解和JoinPoint對(duì)象來(lái)生成。
     *
     * @param rateLimiter LimiterToShareApi注解,用于獲取限流配置信息。
     * @param point       JoinPoint對(duì)象,用于獲取目標(biāo)方法的信息。
     * @return 生成的用于限流的組合鍵字符串。
     */
    public String getCombineKey(LimiterToShareApi rateLimiter, JoinPoint point) {
        // 創(chuàng)建一個(gè)StringBuffer用于拼接組合鍵
        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key() + "-");

        // 根據(jù)LimterToShareApi注解的limitType判斷是否需要添加IP地址信息到組合鍵中【判斷限流類型 是否根據(jù)ip進(jìn)行限流】
        if (rateLimiter.limitType() == LimitType.IP) {
            // 如果需要添加IP地址信息,調(diào)用IpUtils.getIpAddr()方法獲取當(dāng)前請(qǐng)求的IP地址,并添加到組合鍵中
            stringBuffer.append(getClientIp()).append("-");
        }

        // 使用JoinPoint對(duì)象獲取目標(biāo)方法的信息
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();

        // 將目標(biāo)方法所屬類的名稱和方法名稱添加到組合鍵中
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());

        // 返回生成的用于限流的組合鍵字符串
        return stringBuffer.toString();
    }


	 /**
     * 獲取調(diào)用方真實(shí)ip [本機(jī)調(diào)用則得到127.0.0.1]
     * 首先嘗試從X-Forwarded-For請(qǐng)求頭獲取IP地址,如果沒(méi)有找到或者為unknown,則嘗試從X-Real-IP請(qǐng)求頭獲取IP地址,
     * 最后再使用request.getRemoteAddr()方法作為備用方案。注意,在多個(gè)代理服務(wù)器的情況下,
     * X-Forwarded-For請(qǐng)求頭可能包含多個(gè)IP地址,我們?nèi)〉谝粋€(gè)IP地址作為真實(shí)客戶端的IP地址。
     */
    public String getClientIp() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("X-Real-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        // 多個(gè)代理服務(wù)器時(shí),取第一個(gè)IP地址
        int index = ipAddress.indexOf(",");
        if (index != -1) {
            ipAddress = ipAddress.substring(0, index);
        }
        return ipAddress;
    }

}

五:哪里需要點(diǎn)哪里

@PostMapping("/接口api")
// 根據(jù)自己業(yè)務(wù)選擇是否需要這些參數(shù),如果是想從數(shù)據(jù)庫(kù)讀取,不填參數(shù)即可
// 這里意思為對(duì)key的限制為 全局 每60秒內(nèi)2次請(qǐng)求,超過(guò)2次則限流
@LimiterToShareApi(key = "key",time = 60,count = 2,limitType = LimitType.DEFAULT)
public AjaxResult selectToUserId(參數(shù)){}


限流(代碼)結(jié)果:
springboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】,spring boot,后端,javaspringboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】,spring boot,后端,javaspringboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】,spring boot,后端,java


解析:

@Before("@annotation(limiter)")- 使用了@Before 來(lái)表示這是一個(gè)切面注解,用于定義在目標(biāo)方法執(zhí)行前執(zhí)行的邏輯

- @annotation(limiter) 中的limiter是指參數(shù)名稱,而不是注解名稱。

- @annotation(limiter) 中的limiter參數(shù)類型為LimiterToShareApi,
表示你將攔截被@LimiterToShareApi注解標(biāo)記的方法,并且可以通過(guò)這個(gè)參數(shù)來(lái)獲取@LimiterToShareApi注解的信息。
如果你想攔截其他注解,只需將第二個(gè)參數(shù)的類型修改為對(duì)應(yīng)的注解類型即可。

普及:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-609972.html

JoinPointSpring AOP中的一個(gè)接口,它代表了在程序執(zhí)行過(guò)程中能夠被攔截的連接點(diǎn)(Join Point)。
連接點(diǎn)指的是在應(yīng)用程序中,特定的代碼塊,比如方法的調(diào)用、方法的執(zhí)行、構(gòu)造器的調(diào)用等。

JoinPointAOP中的作用是用于傳遞方法調(diào)用的信息,比如方法名、參數(shù)、所屬的類等等。
當(dāng)AOP攔截到一個(gè)連接點(diǎn)時(shí),就可以通過(guò)JoinPoint對(duì)象來(lái)獲取這些信息,并根據(jù)需要進(jìn)行相應(yīng)的處理。

在AOP中,常見(jiàn)的通知類型(advice)如下:

@Before:在目標(biāo)方法執(zhí)行之前執(zhí)行。
@After:在目標(biāo)方法執(zhí)行之后(無(wú)論是否拋出異常)執(zhí)行。
@AfterReturning:在目標(biāo)方法成功執(zhí)行之后執(zhí)行。
@AfterThrowing:在目標(biāo)方法拋出異常后執(zhí)行。
@Around:在目標(biāo)方法執(zhí)行前后都執(zhí)行,可以控制目標(biāo)方法的執(zhí)行。

在以上各種通知中,可以使用JoinPoint參數(shù)來(lái)獲取連接點(diǎn)的相關(guān)信息。
例如,在@Around通知中,可以使用JoinPoint對(duì)象來(lái)獲取目標(biāo)方法的信息,
比如方法名、參數(shù)等。這樣,我們就可以根據(jù)這些信息來(lái)實(shí)現(xiàn)我們需要的切面邏輯。


eg:
// 獲取方法名
String methodName = joinPoint.getSignature().getName();

//獲取方法參數(shù)
Object[] args = joinPoint.getArgs();

// 獲取所屬類名
String className = joinPoint.getSignature().getDeclaringTypeName();

// 獲取源代碼位置信息
SourceLocation sourceLocation = joinPoint.getSourceLocation();

到了這里,關(guān)于springboot 自定義注解 ,實(shí)現(xiàn)接口限流(計(jì)數(shù)器限流)【強(qiáng)行喂飯版】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • go-zero 是如何實(shí)現(xiàn)計(jì)數(shù)器限流的?

    go-zero 是如何實(shí)現(xiàn)計(jì)數(shù)器限流的?

    原文鏈接: 如何實(shí)現(xiàn)計(jì)數(shù)器限流? 上一篇文章 go-zero 是如何做路由管理的? 介紹了路由管理,這篇文章來(lái)說(shuō)說(shuō)限流,主要介紹計(jì)數(shù)器限流算法,具體的代碼實(shí)現(xiàn),我們還是來(lái)分析微服務(wù)框架 go-zero 的源碼。 在微服務(wù)架構(gòu)中,一個(gè)服務(wù)可能需要頻繁地與其他服務(wù)交互,而過(guò)多

    2024年02月13日
    瀏覽(18)
  • Spring Boot 3自定義注解+攔截器+Redis實(shí)現(xiàn)高并發(fā)接口限流

    在當(dāng)今互聯(lián)網(wǎng)應(yīng)用開(kāi)發(fā)中,高并發(fā)訪問(wèn)是一個(gè)常見(jiàn)的挑戰(zhàn)。為了保障系統(tǒng)的穩(wěn)定性和可靠性,我們需要對(duì)接口進(jìn)行限流,防止因過(guò)多的請(qǐng)求導(dǎo)致系統(tǒng)崩潰。 本文將介紹如何利用Spring Boot 3中的自定義注解、攔截器和Redis實(shí)現(xiàn)高并發(fā)接口限流,幫助程序員解決這一挑戰(zhàn)。 1. 自定

    2024年04月28日
    瀏覽(25)
  • go限流、計(jì)數(shù)器固定窗口算法/計(jì)數(shù)器滑動(dòng)窗口算法

    go限流、計(jì)數(shù)器固定窗口算法/計(jì)數(shù)器滑動(dòng)窗口算法

    問(wèn)題1:后端接口只能支撐每10秒1w個(gè)請(qǐng)求,要怎么來(lái)保護(hù)它呢? 問(wèn)題2:發(fā)短信的接口,不超過(guò)100次/時(shí),1000次/24小時(shí),要怎么實(shí)現(xiàn)? 所謂固定窗口,就是只設(shè)置了一個(gè)時(shí)間段,給這個(gè)時(shí)間段加上一個(gè)計(jì)數(shù)器。 常見(jiàn)的就是統(tǒng)計(jì)每秒鐘的請(qǐng)求量。 這里就是一個(gè)QPS計(jì)數(shù)器。 在這一

    2024年04月26日
    瀏覽(21)
  • Springboot 中使用 Redisson+AOP+自定義注解 實(shí)現(xiàn)訪問(wèn)限流與黑名單攔截

    Springboot 中使用 Redisson+AOP+自定義注解 實(shí)現(xiàn)訪問(wèn)限流與黑名單攔截

    ??? 個(gè)人主頁(yè) :牽著貓散步的鼠鼠? ??? 系列專欄 :Java全棧-專欄 ??? 個(gè)人學(xué)習(xí)筆記,若有缺誤,歡迎評(píng)論區(qū)指正 ? 前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站AI學(xué)習(xí)網(wǎng)站。 目錄 前言 1.導(dǎo)入Redisson 引入依

    2024年02月21日
    瀏覽(22)
  • 限流:計(jì)數(shù)器、漏桶、令牌桶 三大算法的原理與實(shí)戰(zhàn)(史上最全)

    限流:計(jì)數(shù)器、漏桶、令牌桶 三大算法的原理與實(shí)戰(zhàn)(史上最全)

    限流是面試中的常見(jiàn)的面試題(尤其是大廠面試、高P面試) 注:本文以 PDF 持續(xù)更新,最新尼恩 架構(gòu)筆記、面試題 的PDF文件,請(qǐng)到文末《技術(shù)自由圈》公號(hào)獲取 為什么要限流 簡(jiǎn)單來(lái)說(shuō): 限流在很多場(chǎng)景中用來(lái)限制并發(fā)和請(qǐng)求量,比如說(shuō)秒殺搶購(gòu),保護(hù)自身系統(tǒng)和下游系統(tǒng)

    2023年04月17日
    瀏覽(21)
  • SpringBoot中通過(guò)自定義Jackson注解實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏

    SpringBoot中通過(guò)自定義Jackson注解實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏

    SpringBoot中整合Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)加解密/數(shù)據(jù)脫敏/數(shù)據(jù)庫(kù)密文,查詢明文: SpringBoot中整合Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)加解密/數(shù)據(jù)脫敏/數(shù)據(jù)庫(kù)密文,查詢明文_霸道流氓氣質(zhì)的博客-CSDN博客 上面講的是數(shù)據(jù)庫(kù)中存儲(chǔ)密文,查詢時(shí)使用明文的脫敏方式,如果是需要數(shù)據(jù)庫(kù)中存儲(chǔ) 明文

    2024年02月16日
    瀏覽(22)
  • SpringBoot中接口冪等性實(shí)現(xiàn)方案-自定義注解+Redis+攔截器實(shí)現(xiàn)防止訂單重復(fù)提交

    SpringBoot中接口冪等性實(shí)現(xiàn)方案-自定義注解+Redis+攔截器實(shí)現(xiàn)防止訂單重復(fù)提交

    SpringBoot+Redis+自定義注解實(shí)現(xiàn)接口防刷(限制不同接口單位時(shí)間內(nèi)最大請(qǐng)求次數(shù)): SpringBoot+Redis+自定義注解實(shí)現(xiàn)接口防刷(限制不同接口單位時(shí)間內(nèi)最大請(qǐng)求次數(shù))_redis防刷_霸道流氓氣質(zhì)的博客-CSDN博客 以下接口冪等性的實(shí)現(xiàn)方式與上面博客類似,可參考。 什么是冪等性? 冪等

    2024年02月15日
    瀏覽(23)
  • 使用 redis 實(shí)現(xiàn)分布式接口限流注解 RedisLimit

    使用 redis 實(shí)現(xiàn)分布式接口限流注解 RedisLimit

    前言 很多時(shí)候,由于種種不可描述的原因,我們需要針對(duì)單個(gè)接口實(shí)現(xiàn)接口限流,防止訪問(wèn)次數(shù)過(guò)于頻繁。這里就用 redis+aop 實(shí)現(xiàn)一個(gè)限流接口注解 @RedisLimit 代碼 點(diǎn)擊查看RedisLimit注解代碼 AOP代碼 點(diǎn)擊查看aop代碼 lua腳本代碼 注意:腳本代碼是放在 resources 文件下的,它的類型是

    2024年02月08日
    瀏覽(28)
  • SpringBoot自定義注解+AOP+redis實(shí)現(xiàn)防接口冪等性重復(fù)提交,從概念到實(shí)戰(zhàn)

    本文為千鋒教育技術(shù)團(tuán)獨(dú)家創(chuàng)作,更多技術(shù)類知識(shí)干貨,點(diǎn)個(gè)關(guān)注持續(xù)追更~ 接口冪等性是Web開(kāi)發(fā)中非常重要的一個(gè)概念,它可以保證多次調(diào)用同一個(gè)接口不會(huì)對(duì)結(jié)果產(chǎn)生影響。如果你想了解更多關(guān)于接口冪等性的知識(shí),那么本文就是一個(gè)不錯(cuò)的起點(diǎn)。 在Web開(kāi)發(fā)中,我們經(jīng)常

    2024年02月03日
    瀏覽(26)
  • LR中監(jiān)控ORACLE數(shù)據(jù)庫(kù)常用計(jì)數(shù)器(如何自定義Oracle計(jì)數(shù)器)

    目錄 一、添加自定義計(jì)數(shù)器的方法 1、要?jiǎng)?chuàng)建自定義查詢,請(qǐng)執(zhí)行以下操作: 2、配置文件示例對(duì)象 二、常用自定義計(jì)數(shù)器列表 三、LR中監(jiān)控ORACLE數(shù)據(jù)庫(kù)常用計(jì)數(shù)器遇到問(wèn)題及處理 1.?在安裝路徑的Mercury LoadRunnerdatmonitors找到vmon.cfg文件,打開(kāi)。 2. 在vmon.cfg文件的第三行中,

    2024年02月15日
    瀏覽(35)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包