我們需要根據(jù)ip去限制用戶單位時間的訪問次數(shù),防止刷手機驗證碼,屏蔽注冊機等,使用注解就非常靈活了
1 定義注解
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documented//最高優(yōu)先級@Order(Ordered.HIGHEST_PRECEDENCE)public @interface RequestLimit { /** * * 允許訪問的次數(shù),默認值MAX_VALUE */ int count() default Integer.MAX_VALUE; /** * * 時間段,單位為毫秒,默認值一分鐘 */ long time() default 60000;}
2 實現(xiàn)注解
@aspect@Componentpublic class RequestLimitContract { private static final Logger logger = LoggerFactory.getLogger("RequestLimitLogger"); @Autowired private RedisTemplate<String, String> redisTemplate; @Before("within(@org.springframework.stereotype.Controller *) && @annotation(limit)") public void requestLimit(final JoinPoint joinPoint, RequestLimit limit) throws RequestLimitException { try { Object[] args = joinPoint.getArgs(); HttpServletRequest request = null; for (int i = 0; i < args.length; i++) { if (args[i] instanceof HttpServletRequest) { request = (HttpServletRequest) args[i]; break; } } if (request == null) { throw new RequestLimitException("方法中缺失HttpServletRequest參數(shù)"); } String ip = HttpRequestUtil.getIpAddr(request); String url = request.getRequestURL().toString(); String key = "req_limit_".concat(url).concat(ip); long count = redisTemplate.opsForValue().increment(key, 1); if (count == 1) { redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS); } if (count > limit.count()) { logger.info("用戶IP[" + ip + "]訪問地址[" + url + "]超過了限定的次數(shù)[" + limit.count() + "]"); throw new RequestLimitException(); } } catch (RequestLimitException e) { throw e; } catch (Exception e) { logger.error("發(fā)生異常: ", e); } }}
3 自定義Exception
public class RequestLimitException extends Exception { private static final long serialVersionUID = 1364225358754654702L; public RequestLimitException() { super("HTTP請求超出設定的限制"); } public RequestLimitException(String message) { super(message); }}
4 在Controller中使用
@RequestLimit(count=100,time=60000)@RequestMapping("/test")public String test(HttpServletRequest request, ModelMap modelMap) { //TODO }
我使用了redis緩存訪問次數(shù),并且設置自增1,其實用靜態(tài)map也可以。
|
新聞熱點
疑難解答