Redisson多策略注解限流(redis 策略)

  本篇文章为你整理了Redisson多策略注解限流(redis 策略)的详细内容,包含有redis注解缓存 redis 策略 rediscache注解 redisson限流实现 Redisson多策略注解限流,希望能帮助你了解 Redisson多策略注解限流。

  生成key的工具类

  根据类型生成锁的对象(key)的工具类,使用map+函数式接口优化if,其中BaseContext是一个获取用户唯一标识userId的工具类

  

@Component

 

  public class ProceedingJoinPointUtil {

   @Autowired

   private HttpServletRequest request;

   private Map LimitType, Function ProceedingJoinPoint,String functionMap = new HashMap (9);

   @PostConstruct

   void initMap(){

   //初始化策略

   functionMap.put(LimitType.METHOD, this::getMethodTypeKey);

   functionMap.put(LimitType.PARAMS, this::getParamsTypeKey);

   functionMap.put(LimitType.USER, this::getUserTypeKey);

   functionMap.put(LimitType.REQUEST_URI,proceedingJoinPoint -

   request.getRequestURI());

   functionMap.put(LimitType.REQUESTURI_USERID, proceedingJoinPoint -

   request.getRequestURI()+BaseContext.getUserId());

   functionMap.put(LimitType.REQUEST_URI_PARAMS,proceedingJoinPoint -

   request.getRequestURI()+getParams(proceedingJoinPoint));

   functionMap.put(LimitType.REQUEST_URI_PARAMS_USERID,proceedingJoinPoint -

   request.getRequestURI()+getParams(proceedingJoinPoint)+BaseContext.getUserId());

   functionMap.put(LimitType.SINGLEUSER,(proceedingJoinPoint)-

   String.valueOf(BaseContext.getUserId()));

   functionMap.put(LimitType.SINGLEMETHOD,(proceedingJoinPoint - {

   StringBuilder sb = new StringBuilder();

   appendMthodName(proceedingJoinPoint,sb);

   return sb.toString();

   }));

   public Object getKey(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {

   //根据限制类型生成key

   Object generateKey = "";

   //自定义

   if(redisLimit.type() != LimitType.CUSTOM){

   generateKey = generateKey(redisLimit.type(), joinPoint);

   }else {

   //非自定义

   generateKey = redisLimit.key();

   return generateKey;

   * 根据LimitType生成key

   * @param type

   * @param joinPoint

   * @return

   private Object generateKey(LimitType type , ProceedingJoinPoint joinPoint) {

   Function function = functionMap.get(type);

   Object result = function.apply(joinPoint);

   return result;

   * 方法级别

   * key = ClassName+MethodName

   * @param joinPoint

   * @return

   private String getMethodTypeKey(ProceedingJoinPoint joinPoint){

   StringBuilder sb = new StringBuilder();

   appendMthodName(joinPoint, sb);

   return sb.toString();

  
private String getParamsTypeKey(ProceedingJoinPoint joinPoint){

   StringBuilder sb = new StringBuilder();

   appendMthodName(joinPoint, sb);

   appendParams(joinPoint, sb);

   return sb.toString();

  
private String getUserTypeKey(ProceedingJoinPoint joinPoint){

   StringBuilder sb = new StringBuilder();

   appendMthodName(joinPoint, sb);

   appendParams(joinPoint, sb);

   //获取userId

   appendUserId(sb);

   return sb.toString();

  
private void appendMthodName(ProceedingJoinPoint joinPoint, StringBuilder sb) {

   Signature signature = joinPoint.getSignature();

   MethodSignature methodSignature = (MethodSignature) signature;

   Method method = methodSignature.getMethod();

   sb.append(joinPoint.getTarget().getClass().getName())//类名

   .append(method.getName());//方法名

   * StringBuilder添加方法参数值

   * @param joinPoint

   * @param sb

   private void appendParams(ProceedingJoinPoint joinPoint, StringBuilder sb) {

   for (Object o : joinPoint.getArgs()) {

   sb.append(o.toString());

   private String getParams(ProceedingJoinPoint joinPoint) {

   StringBuilder sb = new StringBuilder();

   for (Object o : joinPoint.getArgs()) {

   if(o instanceof MultipartFile){

   try {

   ImageTypeCheck.getImgHeightAndWidth(((MultipartFile) o).getInputStream());

   } catch (IOException e) {

   throw new BusinessException("MultipartFile输入流获取失败,source:ProceedingJoinPointUtils.149",USER_PRINCIPAL_EMAIL);

   }else {

   sb.append(o.toString());

   return sb.toString();

   * StringBuilder添加UserId

   * @param sb

   private void appendUserId(StringBuilder sb) {

   sb.append(BaseContext.getUserId());

  

 

  定义aop具体逻辑

  

@Aspect

 

  @Component

  @Slf4j

  public class RedisLimitAspect {

   @Autowired

   private RedissonClient redissonClient;

   @Autowired

   private ProceedingJoinPointUtil proceedingJoinPointUtil;

   @Pointcut("@annotation(com.cat.www.aop.limit.anno.RedisLimit)")

   private void pointCut() {

   @Around("pointCut() @annotation(redisLimit)")

   private Object around(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {

   Object generateKey = proceedingJoinPointUtil.getKey(joinPoint, redisLimit);

   //redis key

   String key = redisLimit.prefix() +generateKey.toString();

   //声明一个限流器

   RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);

   //设置速率,time秒中产生count个令牌

   rateLimiter.trySetRate(RateType.OVERALL, redisLimit.count(), redisLimit.time(), RateIntervalUnit.SECONDS);

   // 试图获取一个令牌,获取到返回true

   boolean tryAcquire = rateLimiter.tryAcquire();

   if (!tryAcquire) {

   return new ResultData ().FAILED().setResultIns("访问过于频繁");

   Object obj = null;

   try {

   obj = joinPoint.proceed();

   } catch (Throwable e) {

   throw new RuntimeException();

   return obj;

  

 

  以上就是Redisson多策略注解限流(redis 策略)的详细内容,想要了解更多 Redisson多策略注解限流的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: