需求:有的时候我们提供给别人接口,但是一般客户并不知道接口的频繁的调用会给服务器带来很大的运行消耗,所以会有频繁请求接口的情况,甚至两次请求的时间间隔都不超过1秒钟,这个时候我们针对同一个用户频繁的请求接口可以进行拦截来告诉用户请求接口过于频繁请稍后请求....
实现上面的需求,我们可能会想到利用缓存的机制
比如用户这次请求,我们存入到缓存中,并且设置一定的保存时间,在这段时间内,如果该用户再一次的请求接口,提示用户请求太过于频繁
针对用户的请求我们可以选择在过滤器中实现这个功能
首先是配置过滤器:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>com.hangxin.xxrest.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
在web.xml配置过滤器,也是就调用以/rest/*结尾的请求接口的时候都会进入该拦截器
我们看看拦截器这个核心应该怎么来编写:
package com.hangxin.xxrest.filter;
import java.io.IOException;
import java.io.PrintWriter;
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;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.json.JSONObject;
public class CORSFilter implements Filter {
private static Cache cache = new Cache("filter", 100, false, false, 60, 10, false, 0);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,PUT,DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Accept,Origin,X-Requested-With,Content-Type,X-Auth-Token");
response.setHeader("Access-Control-Allow-Credentials", "true");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String applyip = request.getRemoteHost();
String applymethod = request.getRequestURI();
String cname = applyip + applymethod;
if (cache.getQuiet(cname) != null) {
JSONObject jsonRtn = new JSONObject();
jsonRtn.put("code", "9999");
jsonRtn.put("msg", "接口请求过于频繁,请休息一下.....");
PrintWriter out = response.getWriter();
out.print(jsonRtn.toString());
} else {
Element element = new Element(cname, 1);
cache.put(element);
chain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
}
}
重点:
首先是创建一个静态的缓存:
private static Cache cache = new Cache("filter", 100, false, false, 60, 10, false, 120);
我们说说一下这个构造函数(有很多,我捡了一个简单的使用)
net.sf.ehcache.Cache.Cache(String name, int maxElementsInMemory, boolean overflowToDisk, boolean eternal, long timeToLiveSeconds, long timeToIdleSeconds, boolean diskPersistent, long diskExpiryThreadIntervalSeconds)
第一个是name:也就是缓存的名称,这个是结合的是缓存管理器 cacheManeger 这个类进行使用
maxElementsInMemory:这个是换存中最大存储的元素的个数
overflowToDisk:如果说缓存中元素的个数太多了怎么处理,true存入到写入到磁盘
eternal:标识的是是否持久化,如果说是true标识的是持久化,如果为false标识不持久化,如果选择持久化这样timeToLiveSeconds 和 timeToIdleSeconds 字段就没用了
timeToLiveSeconds 元素在缓存中保存的时间
timeToIdleSeconds 元素在缓存中的最大的空闲时间,如果大于空闲时间,元素会被清除
diskPersistent:设定在虚拟机重启时是否进行磁盘存储,默认为false
diskExpiryThreadIntervalSeconds 磁盘中的文件是否过期,检验的频率 时间间隔
String applyip = request.getRemoteHost();
String applymethod = request.getRequestURI();
String cname = applyip + applymethod;
if (cache.getQuiet(cname) != null) {
JSONObject jsonRtn = new JSONObject();
jsonRtn.put("code", "9999");
jsonRtn.put("msg", "接口请求过于频繁,请休息一下.....");
PrintWriter out = response.getWriter();
out.print(jsonRtn.toString());
} else {
Element element = new Element(cname, 1);
cache.put(element);
chain.doFilter(servletRequest, servletResponse);
}
我可以获取到请求方的地址和请求的方法
首先判断缓存中是否存在,如果缓存中存在则是因为请求过于频繁
如果缓存中不存在,将其存入到缓存中,并且调用接口方法
上面主要是缓存的一个小小的应用吧
希望对你有所帮助
查看原文: