Limit标签接口 , 实现注解方式
package com.hcfc.auto.util.limit;import java.lang.annotation.*;/** * @创建人 peng.wang * @描述 */@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Limit {}
LimitAspect 切面的实现 , 实现接口屏蔽和限流的逻辑
package com.hcfc.auto.util.limit;import com.hcfc.auto.vo.response.ResponseDto;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestMApping;import java.lang.reflect.Method;import java.util.concurrent.TimeUnit; /** * @创建人 peng.wang * @创建时间 2019/10/11 * @描述 */@Slf4j@Aspect@Componentpublic class LimitAspect {private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);@Autowiredprivate AccessLimiter limiter;@AutowiredGenerateRedisKey generateRedisKey;@Pointcut("@annotation(com.hcfc.auto.util.limit.Limit)")public void limitPointcut() {}@Around("limitPointcut()")public Object doArround(ProceedingJoinPoint joinPoint) throws Throwable {String redisKey = generateRedisKey.getMethodUrlConvertRedisKey(joinPoint);long per = limiter.getPer(redisKey);long times = limiter.getTimes(redisKey);TimeUnit unit = limiter.getUnit(redisKey);boolean isRefresh =limiter.getIsRefresh(redisKey);boolean methodLimitStatus = limiter.isStatus(redisKey);String bindingKey = genBindingKey(joinPoint);if (methodLimitStatus) {logger.info("method is closed, key: ", bindingKey);return ResponseDto.fail("40007", "method is closed, key:"+bindingKey);//throw new OverLimitException("method is closed, key: "+bindingKey);}if(bindingKey !=null){boolean isLimited = limiter.isLimited(bindingKey, times, per, unit);if(isLimited){logger.info("limit takes effect: {}", bindingKey);return ResponseDto.fail("40006", "access over limit, key: "+bindingKey);//throw new OverLimitException("access over limit, key: "+bindingKey);}}Object result = null;result = joinPoint.proceed();if(bindingKey!=null && isRefresh) {limiter.refreshLimited(bindingKey);logger.info("limit refreshed: {}", bindingKey);}return result;}private String genBindingKey(ProceedingJoinPoint joinPoint){try{Method m = ((MethodSignature) joinPoint.getSignature()).getMethod();return joinPoint.getTarget().getClass().getName() + "." + m.getName();}catch (Throwable e){return null;}}}
还有一个不重要的RedisKey实现类GenerateRedisKey和一个错误封装类 , 目前没有使用到 , 使用项目中其他的错误封装类了 。
GenerateRedisKey
package com.hcfc.auto.util.limit;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestMapping;import java.lang.reflect.Method; /** * @创建人 peng.wang * @描述 */@Componentpublic class GenerateRedisKey {public String getMethodUrlConvertRedisKey(ProceedingJoinPoint joinPoint){StringBuilder redisKey =new StringBuilder("");Method m = ((MethodSignature)joinPoint.getSignature()).getMethod();RequestMapping methodAnnotation = m.getAnnotation(RequestMapping.class);if (methodAnnotation != null) {String[] methodValue = https://www.isolves.com/it/sjk/Redis/2022-03-24/methodAnnotation.value();String dscUrl = diagonalLineToCamel(methodValue[0]);return redisKey.append("RSK:").append("interfaceIsOpen:").append(dscUrl).toString();}return redisKey.toString();}private String diagonalLineToCamel(String param){char UNDERLINE='/';if (param==null||"".equals(param.trim())){return "";}int len=param.length();StringBuilder sb=new StringBuilder(len);for (int i = 1; i < len; i++) {char c=param.charAt(i);if (c==UNDERLINE){if (++i
其实有更成熟的方案就是谷歌的Guava , 领导说现在是咱们是分布式 , 不支持 , 还是用Redis实现吧 , 目前就这样实现了 。其实我是新来的 , 好多东西还不太明白 , 很多决定都是上面决定的 , 我只是尽力实现罢了 。不足之处 , 请多多指教!
推荐阅读
- 一次关于架构的“嘴炮”
- 羡慕BI软件的可视化?Python终于可以做出联动可视化报告
- Nginx反向代理Grafana服务的配置步骤
- 12 个优化 Docker 镜像安全性的技巧
- 免费开源的视频直播/录制 OBS Studio 上架 Steam
- 24 张图搞定 ICMP:最常用的网络命令 ping 和 tracert
- 泡沫红茶用什么茶,泡沫红茶饮料
- 泡红茶需要多少度的水,绿茶多少度的水
- 红茶功夫茶的泡法,红茶包的泡法
- 红茶滇红作用,红茶的泡多长时间