权威的顺德网站建设,网站不备案不能访问,微信公众号平台入口官网,网站 硬件方案逻辑#xff1a;写一个注解#xff0c;自定义在多少秒内限制访问多少次。
自定义拦截器#xff0c;对于加了注解的请求#xff0c;在执行方法前。先检查有没有注解#xff0c;如果有注解就将请求的ipurl拼接作为key。
查询redis中有没有该key#xff0c;没有就存入写一个注解自定义在多少秒内限制访问多少次。
自定义拦截器对于加了注解的请求在执行方法前。先检查有没有注解如果有注解就将请求的ipurl拼接作为key。
查询redis中有没有该key没有就存入key1注解中设置的时间限制单位
如果redis有该key就将原来的value取出1
1.自定义注解
import java.lang.annotation.*;
Inherited
Documented
Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface AccessLimit {int limit() default 5;int sec() default 5;
}2.拦截器
在springboot中自定义拦截器实现HandlerInterceptor接口。实现三个方法preHandle()//请求到达controller前
postHandle()//请求到达controller后
afterCompletion()//渲染视图后调用
import com.qcby.xmdemo.annocation.AccessLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Component
public class AccessLimitInterceptor implements HandlerInterceptor {Autowiredprivate RedisTemplate redisTemplate;Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod (HandlerMethod) handler;Method method handlerMethod.getMethod();if (!method.isAnnotationPresent(AccessLimit.class)) {return true;}AccessLimit accessLimit method.getAnnotation(AccessLimit.class);if (accessLimit null) {return true;}int limit accessLimit.limit();int sec accessLimit.sec();String key getIpAddr(request) request.getRequestURI();Integer maxLimit (Integer) redisTemplate.opsForValue().get(key);if (maxLimit null) {redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS);//set时一定要加过期时间} else if (maxLimit limit) {redisTemplate.opsForValue().set(key, maxLimit 1, sec, TimeUnit.SECONDS);} else {output(response, 请求太频繁!);return false;}}return true;}public void output(HttpServletResponse response, String msg) throws IOException {response.setContentType(application/json;charsetUTF-8);ServletOutputStream outputStream null;try {outputStream response.getOutputStream();outputStream.write(msg.getBytes(UTF-8));} catch (IOException e) {e.printStackTrace();} finally {outputStream.flush();outputStream.close();}}Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}//获取请求ip的方法private static String getIpAddr(HttpServletRequest request) {ListString ipHeadList Stream.of(X-Forwarded-For, Proxy-Client-IP, WL-Proxy-Client-IP, HTTP_CLIENT_IP, X-Real-IP).collect(Collectors.toList());for (String ipHead : ipHeadList) {if (checkIP(request.getHeader(ipHead))) {return request.getHeader(ipHead).split(,)[0];}}return 0:0:0:0:0:0:0:1.equals(request.getRemoteAddr()) ? 127.0.0.1 : request.getRemoteAddr();}private static boolean checkIP(String ip) {return !(null ip || 0 ip.length() || unknown.equalsIgnoreCase(ip));}}3.注册拦截器
注册到Spring MVC的拦截器链中。实现WebMvcConfigurer接口并重写addInterceptors()方法来实现。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;Configuration
public class InterceptorConfig implements WebMvcConfigurer {AutowiredAccessLimitInterceptor accessLimitInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(accessLimitInterceptor).addPathPatterns(/**)//拦截所有的路径.excludePathPatterns(/LoginCntroller/login);}
}
4.测试
Controller
RequestMapping(/hello)
public class AopController {ResponseBodyRequestMapping(/index)AccessLimit(limit 4,sec 10)//加上自定义注解即可public String test (HttpServletRequest request, RequestParam(value username,required false) String userName) {return hello!;}}