注釈スタイルを使用します
1)コメントを定義します。
@Retention(RUNTIME) @Target(METHOD) パブリック@interfaceのAccessLimit { int型秒()。 int型MAXCOUNT(); }
2)注釈このような従来の方法は、流量制限器を必要とする追加
@AccessLimit(秒= 5、MAXCOUNT = 5)
3)インターセプタの判断において、この方法は、修飾AccessLimitコメントを使用するかどうかを確認し
@Component パブリック クラスAccessInterceptorはHandlerInterceptorAdapter {延び @Autowired ; MiaoshaUserService miaoshaUserServiceを @Autowired RedisService redisService。 @Override 公共preHandle(HttpServletRequestのリクエスト、HttpServletResponseの応答、オブジェクト・ハンドラ)ブール 例外{スロー システム。アウト(.println " prehandle .... " ); もし(ハンドラのinstanceof HandlerMethod){ HandlerMethod HM = (HandlerMethod)ハンドラ。 文字列methodNameの =hm.getMethod()のgetName();. IF(methodName.equals(" toLogin ")|| methodName.equals(" do_login " )){ リターン trueに; } 他{ // スレッドコンテキストへのユーザーのログイン情報を取得する MiaoshaUser =ユーザーのgetUser(要求、応答); UserContext.setUser(ユーザ); // 限定ブラシ抗分析注釈 accessLimit accessLimit = hm.getMethodAnnotation(accessLimit。クラス); IF(accessLimit == NULL ){ 返す 真; } int型秒= accessLimit.seconds()。 INT MAXCOUNT = accessLimit.maxCount()。 文字列キー = request.getRequestURI()。 ACCESSKEY AK = AccessKey.withExpire(秒)。 整数カウント = redisService。取得(AK、キー、Integer型。クラス); もし(カウント== nullの){ redisService。セット(AK、キー、1 )。 } 他 もし(カウント< MAXCOUNT){ redisService.incr(AK、キー) } 他{ (応答、CodeMsg.ACCESS_LIMIT_REACHED)をレンダリングします。 リターン はfalse ; } } } 戻り 真。 } プライベート ボイドがレンダリング(HttpServletResponseの応答、CodeMsg CM)は例外{スロー response.setContentType(" アプリケーション/ JSONを、文字セット= UTF-8 " )。 OutputStream アウト = response.getOutputStream()。 文字列str = JSON.toJSONString(Result.error(CM))。 アウト .WRITE(str.getBytes(" UTF-8 " )); アウト.flush(); アウト.close(); } プライベートMiaoshaUserのgetUser(HttpServletRequestのリクエスト、HttpServletResponseの応答){ 文字列paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN)。 ストリングcookieToken = getCookieValue(リクエスト、MiaoshaUserService.COOKI_NAME_TOKEN)。 場合(StringUtils.isEmpty(cookieToken)&& StringUtils.isEmpty(paramToken)){ スロー 新しいをGlobalException(CodeMsg.SESSION_ERROR)。 } 文字列トークン = StringUtils.isEmpty(paramToken)?cookieToken:paramToken。
//这里是从Redisの中取用户信息 MiaoshaUser miaoshaUser = miaoshaUserService.getByToken(応答、トークン)。 もし(ヌル == miaoshaUser){ スロー 新しいGlobalException(CodeMsg.SESSION_ERROR)。 } 戻り miaoshaUserと、 } プライベートストリングgetCookieValue(HttpServletRequestの要求は、文字列cookiName){ クッキー[]クッキー = request.getCookies()。 もし(クッキー== NULL || cookies.length <= 0 ){ 戻り ヌル。 } のための(クッキークッキー:クッキー){ 場合(cookie.getName()に等しい(cookiName)){ 戻りcookie.getValueを(); } } 戻り ヌル。 } }
パブリック クラスUserContext { プライベート 静的にThreadLocal <MiaoshaUser> userHolder = 新規のThreadLocal <MiaoshaUser> (); パブリック 静的 ボイドSETUSER(MiaoshaUserユーザ){ userHolder。セット(ユーザ)。 } パブリック 静的MiaoshaUserのgetUser(){ 戻り userHolder。取得(); } }
アイデアがある:キーとして第1の上、ユーザIDとURLスプライシング後のユーザ要求は、1 Redisの値などの値に設定され、有効期限が設定されています。値は、アクセスの最大数を超えた場合、次回は、増分の使用を介してユーザの要求は、ユーザーがアクセスを拒否され、Redisの。