javaweb|jeecgboot接口限制每ip每分钟访问次数——限制ip请求频率【伸手党福利】

代码借鉴的别人的,自己做过部分修改
1. 新建文件夹并新建文件 \jeecg-boot-base\jeecg-boot-base-core\src\main\java\org\jeecg\common\accesslimit\
RequestLimit.java

package org.jeecg.common.accesslimit; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import java.lang.annotation.*; /** * @author wangdeqiu * @date 2018年11月2日 下午2:19:05 * 类说明:自定义注解限制访问时间长度最多访问次数 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit {/** * 允许访问的最大次数 */ int count() default Integer.MAX_VALUE; /** * 时间段,单位为毫秒,默认值一分钟 */ long time() default 60000; }

RequestLimitContract.java
package org.jeecg.common.accesslimit; /** * @Author: wcb * @Date: 2020/7/8 0008 17:05 * @Title: RequestLimitContract * @Version 1.0 *///import com.suoeryun.website.utils.RedisUtil; //import com.suoeryun.website.utils.oConvertUtils; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.jeecg.common.util.RedisUtil; import org.jeecg.common.util.oConvertUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.util.TimerTask; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @Aspect @Component public class RequestLimitContract {private static final Logger logger = LoggerFactory.getLogger(RequestLimitContract.class); @Autowired private RedisUtil redis; private ScheduledExecutorService executorService2; public RequestLimitContract() { executorService2 = new ScheduledThreadPoolExecutor(8, new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()); }@Before("within(@org.springframework.web.bind.annotation.RestController *) && @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参数"); } //如果不限定ip,则设定ip为本机ip //String ip = request.getLocalAddr(); //如果限定ip,则设定ip为客户端的ip String ip = request.getRemoteAddr(); String url = request.getRequestURL().toString(); System.out.println(ip); System.out.println(url); String key = "req_limit_".concat(url).concat(ip); if (!redis.hasKey(key) || oConvertUtils.isEmpty(redis.get(key))) { redis.set(key, String.valueOf(1)); } else { Integer getValue = https://www.it610.com/article/Integer.parseInt((String) redis.get(key)) + 1; redis.set(key, String.valueOf(getValue)); } int count = Integer.parseInt((String) redis.get(key)); if (count> 0) { //创建一个定时器 //Timer timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { redis.del(key); } }; //这个定时器设定在time规定的时间之后会执行上面的remove方法,也就是说在这个时间后它可以重新访问 //timer.schedule(timerTask, limit.time()); // 利用线程池 executorService2.schedule(timerTask, limit.time() / 1000, TimeUnit.SECONDS); } System.out.println(count); if (count > limit.count()) { /*logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]"); throw new RequestLimitException(); String toLomitPath ="http://" + request.getServerName()+ ":" + request.getServerPort()+limitPath; //端口号 response.sendRedirect(toLomitPath); */ logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]"); throw new RequestLimitException("您的请求次数超限!"); } } catch (RequestLimitException e) { throw e; } catch (Exception e) { logger.error("警告,RequestLimit(次数限制)发生致命异常:", e); } }}

RequestLimitException.java
package org.jeecg.common.accesslimit; /** * @author wangdeqiu * @date 2018年11月2日 下午2:22:28 * 类说明: */ public class RequestLimitException extends RuntimeException{private static final long serialVersionUID = 1555967171104727461L; public RequestLimitException(){ super("HTTP请求超出设定的限制"); }public RequestLimitException(String message){ super(message); }}

原作者的注释我没有去掉,但是原作者给出的代码无法限定每ip,只能限制访问次数。
2. jeecgboot全局添加错误形式 \jeecg-boot-base\jeecg-boot-base-core\src\main\java\org\jeecg\common\exception\JeecgBootExceptionHandler.java
@ExceptionHandler(RequestLimitException.class) public Result requestLimitException(RequestLimitException e) { log.error(e.getMessage() + "***********---------------", e); // 返回错误信息 return Result.error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, e.getMessage()); }

调用 【javaweb|jeecgboot接口限制每ip每分钟访问次数——限制ip请求频率【伸手党福利】】关键词:
@RequestLimit(count = 3)

示例:
@RequestLimit(count = 3) @AutoLog(value = "https://www.it610.com/article/测试频率") @ApiOperation("测试频率(组件化版)") @GetMapping(value = "https://www.it610.com/testlimit") public Result testlimit( HttpServletRequest request) { System.out.println("测试频率!!"); return Result.OK("ans"); }

效果:结果 成功
javaweb|jeecgboot接口限制每ip每分钟访问次数——限制ip请求频率【伸手党福利】
文章图片

失败
javaweb|jeecgboot接口限制每ip每分钟访问次数——限制ip请求频率【伸手党福利】
文章图片

效果:每分钟限制访问次数,该限制在每分钟的0秒时刷新(不是在第一次请求时刷新)。
示例: 以3次每ip每分钟为例: javaweb|jeecgboot接口限制每ip每分钟访问次数——限制ip请求频率【伸手党福利】
文章图片

    推荐阅读