java控制api请求接口的次数(附代码)

    本功能的基本思想就是全局增加一个过滤器filter,,如果在指定设置时间内超过请求次数,就进行拦截。目的是为了防止有人恶意侵占资源,导致正常的请求无法响应。以下只是最简单的实现方式,需要的话可以自行拓展。

1.建立四个类

    AccessStatus.java

    CommonService.java

    FrequentAccessControlFilter.java

    FrequentAccessController.java

2.AccessStatus.java类

package com.daxiang;

public class AccessStatus {
	//初次请求时间
    private long lastTime;
    //请求计数
    private  int count;
    //是否已经处理
    private boolean isProcessed;
    public AccessStatus(){
        this.lastTime = System.currentTimeMillis();
        this.count = 1;
    }
    //getter/setter省略
}

3.FrequentAccessController.java类

package com.daxiang;

import java.util.LinkedHashMap;

import javax.servlet.http.HttpServletRequest;

public class FrequentAccessController {

	private static final LinkedHashMap<String, AccessStatus> accessMap = new LinkedHashMap<>();
	// 限制时间 = 1000(毫秒)
	private int timeInterval=1000 ;
	// 开放时间 = 5000(毫秒)
	private int waitTime=5000 ;
    // 在限制时间内的请求的次数 = 50
    private int maxReq=50;
	
    public boolean isFrequentAccess(HttpServletRequest request) {
    	// key 用token和url表示
    	String key = request.getRequestURL().toString();
    	key=key + ( request.getHeader("TK_AUTHEN_TOKEN"));
        AccessStatus status;
        long currTime = System.currentTimeMillis();
        if (accessMap.containsKey(key)) {
            status = accessMap.get(key);
            if (currTime - status.getLastTime() < timeInterval) {
                int count = status.getCount();
                if (count > maxReq) {
                    return true;
                } else {
                    count = count + 1;
                    status.setCount(count);
                }
            } else {
                if (currTime - status.getLastTime() > waitTime) {
                    accessMap.remove(key);
                } 
        } else {
            accessMap.put(key, new AccessStatus());
        }
        return false;
    }

    public static LinkedHashMap<String, AccessStatus> getAccessMap() {
        return accessMap;
    }

    public int getMaxReq() {
        return maxReq;
    }

    public void setMaxReq(int maxReq) {
        this.maxReq = maxReq;
    }

    public int getTimeInterval() {
        return timeInterval;
    }

    public void setTimeInterval(int timeInterval) {
        this.timeInterval = timeInterval;
    }

    public int getWaitTime() {
        return waitTime;
    }

    public void setWaitTime(int waitTime) {
        this.waitTime = waitTime;
    }
}

4.  FrequentAccessControlFilter.java类

package com.daxiang;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FrequentAccessControlFilter  implements Filter {
	
	private final static FrequentAccessController frequentAccessControl = new FrequentAccessController();

	// 拦截的请求方式  只拦截post请求(想拦截其他的请求方式可以自行添加)
    private final static String methodName="POST";
	
	@Override
	public void destroy() {
		
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (frequentAccessControl.isFrequentAccess(request) && methodName.equals(request.getMethod())) {
            response.setHeader("msg", "Too frequent requests");
            response.sendError(403);
            return;
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

}

5. CommonService.java类

package com.daxiang;

import java.util.LinkedHashMap;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service("commonService")
public class CommonService {
	
	// 防止内存占用过多  每10分钟清除一次内存
	@Scheduled(cron="0 0/10 * * * ?")
	public void destoryDosFilter(){
		LinkedHashMap< String, AccessStatus> map=FrequentAccessController.getAccessMap();
		map.clear();
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值