Using annotation style
1) Define a comment
@Retention(RUNTIME) @Target(METHOD) public @interface AccessLimit { int seconds(); int maxCount(); }
2) add annotations such prior methods require a flow restrictor
@AccessLimit(seconds=5, maxCount=5)
3) In the judgment of interceptors, to see whether the method uses a modified AccessLimit comment
@Component public class AccessInterceptor extends HandlerInterceptorAdapter{ @Autowired MiaoshaUserService miaoshaUserService; @Autowired RedisService redisService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("prehandle...."); if(handler instanceof HandlerMethod) { HandlerMethod hm = (HandlerMethod)handler; String methodName =hm.getMethod () getName ();. IF (methodName.equals ( " toLogin " ) || methodName.equals ( " do_login " )) { return to true ; } the else { // Get the user login information into the thread context MiaoshaUser = User the getUser (Request, Response); UserContext.setUser (User); // Analyzing brush anti limiting annotation AccessLimit accessLimit = hm.getMethodAnnotation (AccessLimit. class ); IF (accessLimit == null ) { return true; } int seconds = accessLimit.seconds(); int maxCount = accessLimit.maxCount(); String key = request.getRequestURI(); AccessKey ak = AccessKey.withExpire(seconds); Integer count = redisService.get(ak, key, Integer.class); if(count == null) { redisService.set(ak, key, 1); }else if(count < maxCount) { redisService.incr(ak, key); }else { render(response, CodeMsg.ACCESS_LIMIT_REACHED); return false; } } } return true; } private void render(HttpServletResponse response, CodeMsg cm)throws Exception { response.setContentType("application/json;charset=UTF-8"); OutputStream out = response.getOutputStream(); String str = JSON.toJSONString(Result.error(cm)); out.write(str.getBytes("UTF-8")); out.flush(); out.close(); } private MiaoshaUser getUser(HttpServletRequest request, HttpServletResponse response) { String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN); String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN); if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) { throw new GlobalException(CodeMsg.SESSION_ERROR); } String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
//这里是从redis中取用户信息 MiaoshaUser miaoshaUser = miaoshaUserService.getByToken(response, token); if(null == miaoshaUser){ throw new GlobalException(CodeMsg.SESSION_ERROR); } return miaoshaUser; } private String getCookieValue(HttpServletRequest request, String cookiName) { Cookie[] cookies = request.getCookies(); if(cookies == null || cookies.length <= 0){ return null; } for(Cookie cookie : cookies) { if(cookie.getName().equals(cookiName)) { return cookie.getValue(); } } return null; } }
public class UserContext { private static ThreadLocal<MiaoshaUser> userHolder = new ThreadLocal<MiaoshaUser>(); public static void setUser(MiaoshaUser user) { userHolder.set(user); } public static MiaoshaUser getUser() { return userHolder.get(); } }
The idea is: a user request after the first over, the user id and url splicing as key, 1 is set to the value as redis values, and set an expiration time. Next time the user requests over the use of increment redis when the value exceeds the maximum number of accesses, the user is denied access.