[SpringMVC] custom annotations limit the number of controller accesses and the number of springmvc accesses
We need to limit the number of visits per unit time based on the IP address, to prevent phone verification codes from being flushed, and to shield registration machines. Annotations are very flexible.
1 Define Annotation
@ Retention (RetentionPolicy. RUNTIME) @ Target (ElementType. METHOD) @ receivented
// Highest priority @ Order (Ordered. HIGHEST_PRECEDENCE) public @ interface RequestLimit {/***** number of times access is allowed. The default value is MAX_VALUE */int count () default Integer. MAX_VALUE;/***** time period, in milliseconds. The default value is one minute */long time () default 60000 ;}
2 Implementation Annotation
@ 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 ("The HttpServletRequest parameter is missing in the method");} 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 ("user IP [" + ip + "] access address [" + url + "] exceeds the limit [" + limit. count () + "]"); throw new RequestLimitException () ;}} catch (RequestLimitException e) {throw e;} catch (Exception e) {logger. error ("exception occurred:", e );}}}
3. custom Exception
Public class RequestLimitException extends Exception {private static final long serialVersionUID = 1364225358754654702L; public RequestLimitException () {super ("HTTP request exceeds the set limit");} public RequestLimitException (String message) {super (message );}}
4. Use in Controller
@RequestLimit(count=100,time=60000)@RequestMapping("/test")public String test(HttpServletRequest request, ModelMap modelMap) { //TODO }
I used redis cache access times and set auto-increment 1. In fact, static map can also be used.