运用redis键的expire时间,控制1一分钟内的访问量

客户端频繁的访问网站,会对网站资源造成很大的压力,所以,需要限制时间段内的访问次数,如果访问过于频繁,应该禁止访问,采用redis实现这一需要,redis中,可以使用expire设置key的生存时间,这一特性很好的满足我们的需求,解决代码如下:

工具类:

package cn.sniper.tjfxpt.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisDataException;
public class RedisUtil {
 
 private static JedisPool jedisPool;
 
 //每分钟允许最大访问次数
 private static int MAX_ALLOWED_TIMES = 60;
 
 static {
  String host = "192.168.31.231";
  int port = 6379;
  
  JedisPoolConfig poolConfig = new JedisPoolConfig();
  poolConfig.setMaxIdle(100);
  poolConfig.setMaxTotal(500);
  poolConfig.setMaxWaitMillis(20000);
  poolConfig.setTestOnBorrow(true);
  
  jedisPool = new JedisPool(poolConfig, host, port);
 }
 
 /**
  * 如果key不存在,设置值,如果key存在,覆盖值
  * @param key
  * @param value
  */
 public static void set(String key, String value) {
  Jedis jedis = jedisPool.getResource();
  jedis.set(key, value);
  //用完后放回连接池
  jedisPool.returnResourceObject(jedis);
 }
 
 /**
  * 如果key不存在,设置值,如果key存在,不做任何操作
  * @param key
  * @param value
  */
 public static void setIfNotExists(String key, String value) {
  Jedis jedis = jedisPool.getResource();
  jedis.setnx(key, value);
  //用完后放回连接池
  jedisPool.returnResourceObject(jedis);
 }
 
 /**
  * 自加1
  * @param key
  * @param value
  */
 public static void incrByOne(String key) {
  Jedis jedis = jedisPool.getResource();
  try {
   //如果key对应的值不是数值型,会报异常
   jedis.incr(key);
  } catch(JedisDataException e) {
   e.printStackTrace();
  }
  //用完后放回连接池
  jedisPool.returnResourceObject(jedis);
 }
 
 /**
  * 判断键是否存在
  * @param key
  * @return
  */
 public static boolean exists(String key) {
  Jedis jedis = jedisPool.getResource();
  return jedis.exists(key);
 }
 
 /**
  * 是否允许访问
  * @param key
  * @return
  */
 public static boolean ifAllowed(String key) {
  boolean flag = true;
  
  Jedis jedis = jedisPool.getResource();
  if(exists(key)) {
   //key对应的value自加1
   jedis.incr(key);
   //取得key对应的value
   String value = jedis.get(key);
   try {
    //如果在60秒的生存周期内的访问次数大于MAX_ALLOWED_TIMES,则不允许访问
    if(Integer.parseInt(value) > MAX_ALLOWED_TIMES) {
     flag = false;
    }
   } catch(RuntimeException e) {
    e.printStackTrace();
   }
  } else {
   //第一次访问,设置初始值1
   jedis.set(key, "1");
   //设置生存时间60秒
   jedis.expire(key, 60);
  }
  
  //用完记得放回,否则池很快就用完
  jedisPool.returnResourceObject(jedis);
  
  return flag;
 }
 
 public static void main(String[] args) {
  //setIfNotExists("sniper", "ccc");
  //set("sniper", "ccc");
  //incrByOne("sniper");
  //System.out.println(exists("sniper"));
  
  for(int i=0; i<70; i++) {
   System.out.println(i + "" + ifAllowed("sniper"));
  }
 }
}

filter拦截器:

package cn.sniper.webkit.filter;
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;
import cn.sniper.tjfxpt.utils.RedisUtil;
public class SecureFilter implements Filter {
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  
 }
 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  boolean ifAllowed = true;
  try {
   HttpServletRequest req = (HttpServletRequest)request;
   HttpServletResponse resp = (HttpServletResponse)response;
   
   String uri = req.getRequestURI();
   
   //ip地址
   String ip = "";
   if (req.getHeader("x-forwarded-for") == null) {
    ip = req.getRemoteAddr();
   } else {
    ip = req.getHeader("x-forwarded-for");
   }
   
   ip = "0:0:0:0:0:0:0:1".equals(ip)?"127.0.0.1":ip;
   
   String key = ip + "-" + uri;
   ifAllowed = RedisUtil.ifAllowed(key);
   if(!ifAllowed) {
    req.getSession().invalidate();
    resp.sendRedirect(req.getContextPath() + "/gotoError.xhtml");
   } else {
    chain.doFilter(request, response);
   }
  //防止因为redis异常导致服务不可用
  } catch(Throwable e) {
   chain.doFilter(request, response);
  }
 }
 @Override
 public void destroy() {
  
 }
}

猜你喜欢

转载自blog.csdn.net/lipr86/article/details/83141753