package com.imyeyu.api.annotation; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import com.imyeyu.java.bean.timi.TimiCode; import com.imyeyu.java.bean.timi.TimiException; import com.imyeyu.spring.TimiSpring; import com.imyeyu.spring.annotation.RequestRateLimitAbstractInterceptor; import com.imyeyu.spring.util.Redis; import com.imyeyu.utils.Time; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * 请求频率限制处理器 * * @author 夜雨 * @since 2021-08-16 18:07 */ @Slf4j @Component public class RequestRateLimitInterceptor extends RequestRateLimitAbstractInterceptor { private static final String KEY_PREFIX = "REQUEST:RATE_LIMIT:"; @Autowired @Qualifier("redisRateLimit") private Redis redis; @Override public boolean beforeRun(HttpServletRequest req, HttpServletResponse resp, String id, int cycle, int limit) { // 键 String key = getKey(id); if (redis.has(key)) { Integer count = redis.get(key); if (count != null) { if (count < limit) { redis.setAndKeepTTL(key, ++count); } else { log.warn("请求频率过高:[" + key + "].C" + count + "L" + limit); throw new TimiException(TimiCode.REQUEST_BAD, "request_rate_limit"); } } return true; } redis.set(key, 0, Time.S * cycle); return true; } private String getKey(String id) { return "%sTIMISERVERAPI:%s:%s".formatted(KEY_PREFIX, TimiSpring.getRequestIP(), id); } }