自定義註解封裝RateLimiter.實例:html
@RequestMapping("/myOrder")api @ExtRateLimiter(value = 10.0, timeOut = 500)服務器 public String myOrder() throws InterruptedException {app System.out.println("myOrder");ui return "SUCCESS";spa }線程 |
@Target(value = ElementType.METHOD)htm @Retention(RetentionPolicy.RUNTIME)對象 public @interface ExtRateLimiter {token double value();
long timeOut(); } |
@Aspect @Component public class RateLimiterAop { // 存放接口是否已經存在 private static ConcurrentHashMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<String, RateLimiter>();
@Pointcut("execution(public * com.it.api.*.*(..))") public void rlAop() { }
@Around("rlAop()") public Object doBefore(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature(); // 使用Java反射技術獲取方法上是否有@ExtRateLimiter註解類 ExtRateLimiter extRateLimiter = signature.getMethod().getDeclaredAnnotation(ExtRateLimiter.class); if (extRateLimiter == null) { // 正常執行方法 Object proceed = proceedingJoinPoint.proceed(); return proceed; } // ############獲取註解上的參數 配置固定速率 ############### // 獲取配置的速率 double value = extRateLimiter.value(); // 獲取等待令牌等待時間 long timeOut = extRateLimiter.timeOut(); RateLimiter rateLimiter = getRateLimiter(value, timeOut); // 判斷令牌桶獲取token 是否超時 boolean tryAcquire = rateLimiter.tryAcquire(timeOut, TimeUnit.MILLISECONDS); if (!tryAcquire) { serviceDowng(); return null; } // 獲取到令牌,直接執行.. Object proceed = proceedingJoinPoint.proceed(); return proceed;
}
// 獲取RateLimiter對象 private RateLimiter getRateLimiter(double value, long timeOut) { // 獲取當前URL ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String requestURI = request.getRequestURI(); RateLimiter rateLimiter = null; if (!rateLimiterMap.containsKey(requestURI)) { // 開啓令牌通限流 rateLimiter = RateLimiter.create(value); // 獨立線程 rateLimiterMap.put(requestURI, rateLimiter); } else { rateLimiter = rateLimiterMap.get(requestURI); } return rateLimiter; }
// 服務降級 private void serviceDowng() throws IOException { // 執行服務降級處理 System.out.println("執行降級方法,親,服務器忙!請稍後重試!"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletResponse response = attributes.getResponse(); response.setHeader("Content-type", "text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); try { writer.println("執行降級方法,親,服務器忙!請稍後重試!"); } catch (Exception e) {
} finally { writer.close(); }
}
public static void main(String[] args) { // 使用Java反射技術獲取方法上是否有@ExtRateLimiter註解類 ExtRateLimiter extRateLimiter = IndexController.class.getClass().getAnnotation(ExtRateLimiter.class); System.out.println(extRateLimiter); }
} |
@RequestMapping("/myOrder") @ExtRateLimiter(value = 10.0, timeOut = 500) public String myOrder() throws InterruptedException { System.out.println("myOrder"); return "SUCCESS"; } |