`

springmvc实现网站限流(HandlerInterceptorAdapter 拦截器)

 
阅读更多
辅助类,用于存储每个请求的访问数
public class AccessCounts {  
  
    public static final String CALLPATH = "AccessCounts.CALLPATH";  
      
    private ConcurrentHashMap<Object, AtomicInteger> map = new ConcurrentHashMap<Object, AtomicInteger>();  
    private AccessCounts() {  
    }  
      
    private static class Instance {  
        static AccessCounts counts = new AccessCounts();  
    }  
      
    public static AccessCounts getInstance() {  
        return Instance.counts;  
    }  
      
    public int get(Object key) {  
        AtomicInteger counter = map.get(key);  
        if (counter == null) {  
            counter = new AtomicInteger(0);  
            map.put(key, counter);  
        }  
        return counter.intValue();  
    }  
      
    public int incrementAndGet(Object key) {  
        AtomicInteger counter = map.get(key);  
        if (counter == null) {  
            counter = new AtomicInteger(0);  
            map.put(key, counter);  
        }  
        return counter.incrementAndGet();  
    }  
      
    public int decrementAndGet(Object key) {  
        AtomicInteger counter = map.get(key);  
        if (counter == null) {  
            return 0;  
        }  
        return counter.decrementAndGet();  
    }  
      
    public String status(){  
        return map.toString();  
    }  
}  


拦截器
/**  
 *限流拦截器  
 **/  
public class InServiceAccessInterceptor extends HandlerInterceptorAdapter {  
  
    private static final Logger logger = Logger.getLogger(InServiceAccessInterceptor.class);  
  
    private ConcurrentHashMap<String, Integer> config = new ConcurrentHashMap<String, Integer>();  
      
    // setting  
    private int defaultLimit = 100;  
      
    private String configUrl = null;  
    private int loadInterval = 1, loadDelay=5;  
    private boolean valid;  
      
    public InServiceAccessInterceptor(int defaultLimit, String configUrl, int loadInterval, int loadDelay, boolean valid) {  
        this.defaultLimit = defaultLimit;  
        this.configUrl = configUrl;  
        this.loadInterval = loadInterval;  
        this.loadDelay = loadDelay;  
        this.valid = valid;  
        if(valid){  
            task();  
        }  
    }  
      
    //before the actual handler will be executed  
    @Override  
    public boolean preHandle(HttpServletRequest request,  
            HttpServletResponse response, Object handler) throws Exception {  
        if(valid){  
            if(handler instanceof HandlerMethod){  
                HandlerMethod handlerMethod = (HandlerMethod) handler;  
                String callpath = handlerMethod.getMethod().getDeclaringClass().getSimpleName()+"."+handlerMethod.getMethod().getName();  
                System.out.println(callpath);  
                int counter = AccessCounts.getInstance().get(callpath);  
                boolean limit = limit(callpath, counter);  
                if (limit) {  
                    throw new IllegalAccessException("Flowing Limit." + callpath + "=" +counter );  
                }  
                MDC.put(AccessCounts.CALLPATH, callpath);  
                AccessCounts.getInstance().incrementAndGet(callpath);  
            }  
        }  
        return true;  
    }  
      
    //after the handler is executed  
    @Override  
    public void postHandle(HttpServletRequest request,  
            HttpServletResponse response, Object handler,  
            ModelAndView modelAndView) throws Exception {  
        if(valid){  
            Object callpath = MDC.get(AccessCounts.CALLPATH);  
            if (null != callpath) {  
                AccessCounts.getInstance().decrementAndGet( callpath);  
            }  
            MDC.remove(AccessCounts.CALLPATH);  
        }  
    }  
      
    @Override  
    public void afterCompletion(HttpServletRequest request,  
            HttpServletResponse response, Object handler, Exception ex)  
            throws Exception {  
        // TODO Auto-generated method stub  
          
    }  
      
    private boolean limit(String callpath, int counter) {  
  
        Integer obj = config.get(callpath);  
        int limit = defaultLimit;  
        if (obj != null) {  
            limit = obj.intValue();  
        }  
        if (logger.isDebugEnabled() ) {  
            logger.debug("check callpath:" + callpath + " limit:" + limit);  
        }  
        if (counter >= limit) {  
            logger.warn("the call[" + callpath + "] is over limit:" + limit + " counter:" + counter);  
            return true;  
        }  
        return false;  
    }  
  
    public static String sendGet(String url, String param) {  
        String result = "";  
        BufferedReader in = null;  
        try {  
            String urlNameString = url + (param == null ? "" : "?" + param);  
            URL realUrl = new URL(urlNameString);  
            // 打开和URL之间的连接  
            URLConnection connection = realUrl.openConnection();  
            // 设置通用的请求属性  
            connection.setRequestProperty("accept", "*/*");  
            connection.setRequestProperty("connection", "Keep-Alive");  
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");  
            // 建立实际的连接  
            connection.connect();  
            // 获取所有响应头字段  
            /*Map<String, List<String>> map = connection.getHeaderFields();  
            for (String key : map.keySet()) {  
                System.out.println(key + "--->" + map.get(key));  
            }*/  
            // 定义 BufferedReader输入流来读取URL的响应  
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));  
            String line;  
            while ((line = in.readLine()) != null) {  
                result += line;  
            }  
        } catch (Exception e) {  
            logger.error("request url fail="+url, e);  
        }  
        // 使用finally块来关闭输入流  
        finally {  
            try {  
                if (in != null) {  
                    in.close();  
                }  
            } catch (Exception e) {  
            }  
        }  
        return result;  
    }  
      
    public void task() {  
        TimerTask task = new TimerTask() {    
            @Override    
            public void run() {   
                if (null == configUrl ) return;  
                String text = sendGet(configUrl, null);  
                logger.info("load config:" + text );  
                if ( null == text || "".equals(text.trim())) return;  
                  
                text = text.replaceAll("[\\{\\}\"\n]", "");  
                config.clear();  
                for (String line : text.split(",")) {  
                    String fields[] = line.split(":");  
                    if ( fields.length < 2) continue;  
                    try {  
                        config.put(fields[0].trim(), Integer.valueOf(fields[1].trim()));  
                    } catch (Exception e) {  
                        logger.error("load config fail.", e);  
                    }  
                }  
            }  
        };  
        Timer timer = new Timer();    
        long delay = 1000 * loadDelay;    
        long intevalPeriod = 1000 * loadInterval;    
        // schedules the task to be run in an interval    
        logger.info("Task setting  delay:" + delay + "  intevalPeriod:" + intevalPeriod);  
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);   
          
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                while (true) {  
                    try {  
                        Thread.sleep(60*1000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("AccessCounts status:" + AccessCounts.getInstance().status());  
                }  
            }  
        }).start();  
  
    }  
      
  
}  


xml配置
<mvc:interceptors>  
        <mvc:interceptor>  
            <mvc:mapping path="/**" />  
            <beans:bean class="xxx.xxx.xxx.intercept.InServiceAccessInterceptor">  
                <beans:constructor-arg index="0" value="1000" /> <!-- defaultLimit 默认设置 -->  
                <beans:constructor-arg index="1" value="http://localhost/web.limit" /> <!-- configUrl    -->  
                <beans:constructor-arg index="2" value="60" /> <!-- loadInterval unit : second -->  
                <beans:constructor-arg index="3" value="5" /> <!-- loadDelay unit : second -->  
                <beans:constructor-arg index="4" value="false" /> <!-- valid  true: used -->  
            </beans:bean>  
        </mvc:interceptor>  
</mvc:interceptors>  


http://localhost/web.limit文件
{"IndexController.index":500,
"ProductController.searchProducts":500
}

http://blog.csdn.net/soleave/article/details/50388549
http://blog.csdn.net/ye_sheng/article/details/48395663
http://www.cnblogs.com/sunp823/p/5601396.html
分享到:
评论

相关推荐

    企业级开发-SpringMVC使用拦截器实现用户登录权限验证实验报告.docx

    本实验报告将探讨如何利用 SpringMVC 的拦截器(Interceptor)来实现用户登录权限验证,确保只有已登录的用户才能访问特定的受保护资源。 首先,我们来看一下实验的基本步骤: 1. 创建 `User` 类:这是表示用户...

    SpringMVC拦截器例子详解

    - 使用Java配置时,可以通过`@EnableWebMvc` 注解启用Web MVC配置,并在`WebMvcConfigurer` 实现类中重写`addInterceptors()` 方法来注册拦截器。 3. **自定义拦截器**: - 自定义拦截器需要继承`...

    SpringMVC 中的拦截器与异常处理

    通过实现`HandlerInterceptor`接口或者继承`HandlerInterceptorAdapter`抽象类,开发者可以定义自己的拦截器。拦截器通常用于实现如登录检查、权限验证、日志记录、性能统计等跨切面的功能。 1. 拦截器的注册:拦截...

    springmvc拦截器实现登录验证

    1. **定义拦截器类**:创建一个实现了Spring MVC的`HandlerInterceptor`接口的类,或者继承`HandlerInterceptorAdapter`抽象类。在这个类中,你需要重写`preHandle()`方法,进行登录验证逻辑。 2. **实现登录验证...

    springmvc传值对象及拦截器

    Spring MVC的拦截器基于AOP(面向切面编程)原理,它们通过实现`HandlerInterceptor`接口或继承`HandlerInterceptorAdapter`抽象类来定义。拦截器链的概念使得多个拦截器可以按照特定顺序执行,每个拦截器都可以决定...

    SpringMVC中使用Interceptor拦截器

    在Spring MVC框架中,Interceptor(拦截器)是一个强大的工具,用于在请求被控制器处理之前或之后执行特定的逻辑。它们可以用来实现通用的功能,如权限验证、日志记录、性能统计等,避免在每个控制器方法中重复编写...

    SpringMVC 限流的示例代码

    在 SpringMVC 中实现限流,可以通过多种方式,例如使用拦截器(Interceptor)、AOP(面向切面编程)或者第三方库。本篇文章将重点介绍如何利用 Google 的 Guava 库在 SpringMVC 中实现限流。 **Guava 限流机制** ...

    springmvc(自定义拦截器的使用)

    以下是对自定义拦截器实现步骤的详细解释: ### 1. 自定义拦截器类 #### 1.1 继承 `HandlerInterceptorAdapter` 你可以选择继承`HandlerInterceptorAdapter`这个抽象类,这是一个已经实现了`HandlerInterceptor`...

    Java实训教程 Java软件开发实战 Java开发框架介绍 SpringMVC_10_拦截器 共7页.pptx

    下面是一个具体的登录状态检测拦截器实现示例,该示例展示了如何使用`HandlerInterceptor`接口来实现登录状态检查功能: ```java public class LoginInterceptor implements HandlerInterceptor { @Override ...

    springMVC拦截器

    要创建自定义拦截器,你需要继承 `HandlerInterceptor` 或实现 `HandlerInterceptorAdapter` 类。这两个类都提供了三个核心方法: 1. `preHandle(HttpServletRequest request, HttpServletResponse response, ...

    SpringMVC文件上传下载分页拦截器

    1. **HandlerInterceptorAdapter**: Spring MVC的拦截器通过实现`HandlerInterceptorAdapter`接口,重写`preHandle`、`postHandle`和`afterCompletion`方法,实现请求前、后处理和异常处理。 2. **全局异常处理**: ...

    SpringMVC学习(十二)——SpringMVC中的拦截器

    在Spring MVC中,拦截器是通过实现`HandlerInterceptor`接口或者继承`HandlerInterceptorAdapter`抽象类来创建的。 `HandlerInterceptor`接口定义了三个方法: 1. `preHandle(HttpServletRequest request, ...

    SpringMVC拦截器的使用

    同时,多个拦截器可以按照指定顺序执行,通过`HandlerInterceptorAdapter`还可以简化拦截器的实现。 在实际开发中,`Interceptor_demo`这个压缩包文件可能包含了示例代码,包括Interceptor的实现以及相关的配置文件...

    Spring MVC 拦截器

    在Spring MVC中,拦截器接口由`HandlerInterceptor`定义,而`HandlerInterceptorAdapter`类则提供了一个适配器模式的默认实现,简化了拦截器的开发过程。`HandlerInterceptor`接口包含以下三个核心方法: 1. **`...

    SpringMVC拦截器——实现登录验证拦截器的示例代码

    首先,我们需要创建一个自定义的拦截器类,该类通常会实现Spring MVC提供的`HandlerInterceptor`接口或继承`HandlerInterceptorAdapter`抽象类。在这个示例中,我们可以定义一个名为`LoginInterceptor`的类,如下: ...

    SpringMVC拦截器

    在这个"SpringMVC拦截器"的实践中,我们将探讨如何实现一个用于登录验证的拦截器。 首先,我们需要创建一个自定义的拦截器类,该类需要继承自Spring MVC的`HandlerInterceptor`接口或实现`...

    springmvc拦截器

    创建一个Spring MVC拦截器需要实现`HandlerInterceptor`接口或者继承`HandlerInterceptorAdapter`抽象类。例如,我们创建一个名为`LoggingInterceptor`的拦截器: ```java public class LoggingInterceptor extends...

    springMVC3学习(七)--Interceptor拦截器(源码)

    在Spring MVC中,Interceptor(拦截器)是一种强大的机制,它允许开发者在请求处理前后执行自定义逻辑,而不必侵入到Controller代码中。本篇文章主要探讨了Interceptor的使用及其源码解析,帮助深入理解其工作原理。...

    spring mvc拦截器过滤json中的null值

    完成拦截器实现后,我们需要在Spring MVC配置中注册它。在`WebMvcConfigurer`的实现类中添加以下代码: ```java @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override ...

    springmvc实现简单的拦截器

    SpringMVC实现简单的拦截器 SpringMVC中实现简单的拦截器是通过HandlerInterceptor来实现的。要定义一个Interceptor,主要有两种方式:第一种方式是定义的Interceptor类要实现了Spring的HandlerInterceptor接口,...

Global site tag (gtag.js) - Google Analytics