使用自定義注解的方式,在需要被限制訪問頻率的方法上加注解即可控制。 看實(shí)現(xiàn)方式,基于springboot,aop,redis。 新建Springboot工程,引入redis,aop。 創(chuàng)建注解 package com.tianyalei.annotation; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import java.lang.annotation.*; /** * Created by wuwf on 17/7/6. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented //最高優(yōu)先級(jí) @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit { /** * 允許訪問的次數(shù) */ int count() default 5; /** * 時(shí)間段,多少時(shí)間段內(nèi)運(yùn)行訪問count次 */ long time() default 60000; } Aspect切面處理邏輯 package com.tianyalei.aspect; import com.tianyalei.annotation.RequestLimit; import com.tianyalei.util.HttpRequestUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * Created by wuwf on 17/7/6. */ @Component @Aspect public class RequestLimitAspect { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private RedisTemplate<String, String> redisTemplate; @Before("execution(public * com.tianyalei.controller.*.*(..)) && @annotation(limit)") public void requestLimit(JoinPoint joinpoint, RequestLimit limit) { // 接收到請(qǐng)求,記錄請(qǐng)求內(nèi)容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String ip = HttpRequestUtil.getIpAddr(request); String url = request.getRequestURL().toString(); String key = "req_limit_".concat(url).concat(ip); //加1后看看值 long count = redisTemplate.opsForValue().increment(key, 1); //剛創(chuàng)建 if (count == 1) { //設(shè)置1分鐘過期 redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS); } if (count > limit.count()) { logger.info("用戶IP[" + ip + "]訪問地址[" + url + "]超過了限定的次數(shù)[" + limit.count() + "]"); throw new RuntimeException("超出訪問次數(shù)限制"); } } } 獲取IP的工具類 package com.tianyalei.util; import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; /** * Created by admin on 17/7/6. */ public class HttpRequestUtil { /** * 獲取當(dāng)前網(wǎng)絡(luò)ip * * @param request * @return */ public static String getIpAddr(HttpServletRequest request) { String ipAddress = request.getHeader("x-forwarded-for"); if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) { //根據(jù)網(wǎng)卡取本機(jī)配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ipAddress = inet.getHostAddress(); } } //對(duì)于通過多個(gè)代理的情況,第一個(gè)IP為客戶端真實(shí)IP,多個(gè)IP按照','分割 if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15 if (ipAddress.indexOf(",") > 0) { ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); } } return ipAddress; } } 通過Controller驗(yàn)證 @RestController public class IndexController { @RequestLimit(count = 4) @GetMapping("/index") public Object index() { return 1; } } 啟動(dòng)工程,多次訪問index看看效果即可。 --------------------- 作者:天涯淚小武 來源:CSDN 原文:https://blog.csdn.net/tianyaleixiaowu/article/details/74549145 版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接! |
|