赞
踩
当用户多次点击按钮,导致多次请求同一连接,在高峰时期更会加大服务器的压力。
因此解决办法就是进行拦截,拦截的方式很多种,这里使用SpringBoot进行拦截示例。
技术实现,通过以下两个组合使用完成
<!-- expiringmap依赖 --> <dependency> <groupId>net.jodah</groupId> <artifactId>expiringmap</artifactId> <version>0.5.8</version> </dependency> <!-- 测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- 网络测试依赖 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <!-- SpringBoot相关依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
配置部分完成。为了整体整洁、精简,特将import部分省去。
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}
@RestController
public class SimpleController {
// @GetMapping("/hello") // 两种写法
@RequestMapping(value = "hello", method = RequestMethod.GET)
public String hello(){
return "{\"code\":\"200\",\"msg\":\"hello\"}";
}
}
以下开始本文内容
,实现拦截器接口(HandlerInterceptor)并且配置配置类(WebMvcConfigurer)
public class CurrentLimitingInterceptor implements HandlerInterceptor { // 设置map为常量 public static final Map<String, ExpiringMap<String,Integer>> map = new ConcurrentHashMap<>(); // preHandle 是调用方法前调用的方法 @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { // 这里假定前端会在请求头中加入 user参数 // 自己测试的时候可以这么写, curl -X GET -H "user:Mr.R" localhost/hello String user = httpServletRequest.getHeader("user"); // user = "Mr.R"; // 如果想在网页看效果,加上这个即可 // 获得请求的URI String requestURI = httpServletRequest.getRequestURI(); // 查找KEY,没有找到就存入过期时间为2s的ExpiringMap(2s如果没有人访问则自动删除,反之刷新2s过期时间) ExpiringMap<String,Integer> em = map.getOrDefault(requestURI, ExpiringMap.builder().expiration(2, TimeUnit.SECONDS).build()); // 这里存入访问次数,当count达到一定次数,拦截器拦截本次请求 Integer count = em.getOrDefault(user, -1); // 此处设置的是2,超过则拒绝访问 if(count>2){ System.out.println(LocalTime.now()+",【ERROR】 Unable to access !!!!!,user\":\""+user); httpServletResponse.getWriter().write("{\"code\":\"400\",\"msg\":\"[ ERROR ] Unable to access\",\"user\":\""+user+"\"}"); httpServletResponse.setStatus(404); em.put(user,++count); System.out.println(map); return false; } em.put(user,++count); map.put(requestURI,em); System.out.println(LocalTime.now()+","+user); // false将不会访问下面方法内容以及 真正要被调用的方法 return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 对所有访问路径,都通过CurrentLimitingInterceptor类型的拦截器进行拦截
registry.addInterceptor(new CurrentLimitingInterceptor()).addPathPatterns("/**");
//这些内容除外,主页,注册页面,登录操作,静态资源
// .excludePathPatterns("/index.html", "/login.html", "/login", "/css/**");
}
}
接下来随便采取一种方式进行测试
提示:在最后放了封装类
public class SimpleTest { public final static String[] users = {"userA","userB","userC"}; @Test public void randomTest() throws InterruptedException { while (true){ Thread.sleep(200); // HttpClientUtil 文章末尾 HttpClientUtil.get("http://localhost/hello",users[new Random().nextInt(3)]); } } @Test public void random1() throws InterruptedException { while (true){ Thread.sleep(500); HttpClientUtil.get("http://localhost/hello",users[0]); } } @Test public void random2() throws InterruptedException { while (true){ Thread.sleep(1100); HttpClientUtil.get("http://localhost/hello",users[1]); } } @Test public void random3() throws InterruptedException { while (true){ Thread.sleep(2000); HttpClientUtil.get("http://localhost/hello",users[2]); } } }
public class HttpClientUtil { static CloseableHttpClient httpClient = HttpClientBuilder.create().build(); public static void get(String url,String user){ // 响应模型 CloseableHttpResponse response = null; try { // 由客户端执行(发送)Get请求 HttpGet request = new HttpGet(url); request.addHeader("user",user); response = httpClient.execute(request); // 从响应模型中获取响应实体 HttpEntity responseEntity = response.getEntity(); System.out.println("响应状态为:" + response.getStatusLine()); if (responseEntity != null) { System.out.println("响应内容长度为:" + responseEntity.getContentLength()); System.out.println("响应内容为:" + EntityUtils.toString(responseEntity)); } }catch (Exception e) { throw new RuntimeException(e); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。