All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jedis.support.ConfigurableJedisPool Maven / Gradle / Ivy

The newest version!
package com.github.jedis.support;

import com.github.autoconf.ConfigFactory;
import com.github.autoconf.api.IChangeListener;
import com.github.autoconf.api.IConfig;
import com.github.autoconf.api.IConfigFactory;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedisPool;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.*;

/**
 * 根据配置得到一个pool
 * Created by lirui on 2015/03/10 下午7:56.
 */
public abstract class ConfigurableJedisPool implements InitializingBean, DisposableBean {
  private static final TimeZone chinaZone = TimeZone.getTimeZone("GMT+08:00");
  private static final Locale chinaLocale = Locale.CHINA;
  private static final Set names = ImmutableSet.of("Boolean", "Character", "Byte", "Short", "Long", "Integer", "Byte", "Float", "Double", "Void", "String");
  private final CharMatcher matcher = CharMatcher.anyOf(", ;|");
  protected Logger log = LoggerFactory.getLogger(getClass());
  private IConfigFactory configFactory;
  private String configName;
  /**
   * 若果有多个服务地址,用Sharded
   */
  private ShardedJedisPool shardedPool = null;
  /**
   * 只有一个服务地址的时候,就用jedis好了,省去很多工作
   */
  private JedisPool pool = null;

  public String getConfigName() {
    return configName;
  }

  public void setConfigName(String configName) {
    this.configName = configName;
  }

  public IConfigFactory getConfigFactory() {
    return configFactory;
  }

  public void setConfigFactory(IConfigFactory configFactory) {
    this.configFactory = configFactory;
  }

  public ShardedJedisPool getShardedPool() {
    return shardedPool;
  }

  public void setShardedPool(ShardedJedisPool shardedPool) {
    this.shardedPool = shardedPool;
  }

  public JedisPool getPool() {
    return pool;
  }

  public void setPool(JedisPool pool) {
    this.pool = pool;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    if (configFactory == null) {
      configFactory = ConfigFactory.getInstance();
    }
    configFactory.getConfig(configName, new IChangeListener() {
      @Override
      public void changed(IConfig config) {
        try {
          loadConfig(config);
        } catch (Exception e) {
          log.error("cannot load: {}", config.getName(), e);
        }
      }
    });
  }

  @Override
  public void destroy() throws Exception {
    close(shardedPool);
  }

  private void close(Closeable c) {
    if (c != null) {
      try {
        c.close();
        c = null;
      } catch (IOException e) {
        log.error("cannot close {}", c, e);
      }
    }
  }

  private void loadConfig(IConfig config) {
    String configServers = config.get("redis.servers");
    if (Strings.isNullOrEmpty(configServers))
      return;
    if (!config.getBool("startup", true)) {
      close(shardedPool);
      shardedPool = null;
      return;
    }

    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxTotal(config.getInt("pool.maxActive", 100));
    poolConfig.setMinIdle(config.getInt("pool.minIdle", 5));
    poolConfig.setMaxIdle(config.getInt("pool.maxIdle", 25));
    poolConfig.setMaxWaitMillis(config.getInt("pool.maxWaitMillis", 3000));
    poolConfig.setTestOnBorrow(config.getBool("pool.testOnBorrow", false));
    poolConfig.setTestOnReturn(config.getBool("pool.testOnReturn", false));
    poolConfig.setTestWhileIdle(config.getBool("pool.testWhileIdle", true));

    if (matcher.countIn(config.get("redis.servers")) > 0) {
      List servers = getJedisShardInfos(config);
      ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, servers);
      if (shardedPool != null) {
        ShardedJedisPool old = shardedPool;
        shardedPool = shardedJedisPool;
        close(old);
      } else {
        shardedPool = shardedJedisPool;
      }
    } else {
      JedisPool jedisPool = createJedisPool(poolConfig, config);
      if (pool != null) {
        JedisPool old = pool;
        pool = jedisPool;
        close(old);
      } else {
        pool = jedisPool;
      }
    }
  }

  private JedisPool createJedisPool(JedisPoolConfig poolConfig, IConfig config) {
    int timeout = config.getInt("redis.timeout", 5000);
    String password = config.get("redis.password");
    int defaultDbIndex = config.getInt("redis.dbIndex", 0);
    String server = config.get("redis.servers");
    List paths = Splitter.on(CharMatcher.anyOf(":/")).splitToList(server);
    String host = paths.get(0);
    int port = 6379, db = defaultDbIndex;
    if (paths.size() > 1) {
      port = Integer.parseInt(paths.get(1));
    }
    if (paths.size() > 2) {
      db = Integer.parseInt(paths.get(2));
    }
    return new JedisPool(poolConfig, host, port, timeout, password, db);
  }

  private List getJedisShardInfos(IConfig config) {
    String configServers = config.get("redis.servers");
    List servers = Lists.newArrayList();
    List items = Splitter.on(matcher).trimResults().omitEmptyStrings().splitToList(configServers);
    int timeout = config.getInt("redis.timeout", 5000);
    String password = config.get("redis.password");
    int defaultDbIndex = config.getInt("redis.dbIndex", 0);
    for (String i : items) {
      List paths = Splitter.on(CharMatcher.anyOf(":/")).splitToList(i);
      String host = paths.get(0);
      int port = 6379, db = defaultDbIndex;
      if (paths.size() > 1) {
        port = Integer.parseInt(paths.get(1));
      }
      if (paths.size() > 2) {
        db = Integer.parseInt(paths.get(2));
      }
      URI redisUri = create(host, port, password, db);
      JedisShardInfo info = new JedisShardInfo(redisUri);
      info.setConnectionTimeout(timeout);
      info.setSoTimeout(timeout);
      if (password != null && password.contains("@")) {
        info.setPassword(password);
      }
      servers.add(info);
    }
    return servers;
  }

  /**
   * redis的密码当中最好不要包含'@'符号,否则处理起来非常麻烦
   *
   * @param host     主机地址
   * @param port     端口号
   * @param password 密码
   * @param dbIndex  db
   * @return 资源地址
   */
  protected URI create(String host, int port, String password, int dbIndex) {
    StringBuilder sbd = new StringBuilder(32);
    sbd.append("redis://");
    if (!Strings.isNullOrEmpty(password) && !password.contains("@")) {
      sbd.append("user:").append(password).append('@');
    }
    sbd.append(host).append(':').append(port);
    if (dbIndex > 0) {
      sbd.append('/').append(dbIndex);
    }
    return URI.create(sbd.toString());
  }

  /**
   * 函数参数信息
   *
   * @param args 参数列表
   * @return 格式化输出
   */
  protected String getParameters(Object[] args) {
    if (args == null)
      return "";
    StringBuilder sbd = new StringBuilder();
    if (args.length > 0) {
      for (Object i : args) {
        if (i == null) {
          sbd.append("null");
        } else {
          Class clz = i.getClass();
          if (isPrimitive(clz)) {
            sbd.append(evalPrimitive(i));
          } else if (clz.isArray()) {
            evalArray(i, sbd);
          } else if (Collection.class.isAssignableFrom(clz)) {
            Object[] arr = ((Collection) i).toArray();
            evalArray(arr, sbd);
          } else if (i instanceof Date) {
            sbd.append('"').append(formatYmdHis(((Date) i))).append('"');
          } else {
            sbd.append(clz.getSimpleName()).append(":OBJ");
          }
        }
        sbd.append(',');
      }
      sbd.setLength(sbd.length() - 1);
    }
    return sbd.toString();
  }

  private boolean isPrimitive(Class clz) {
    return clz.isPrimitive() || names.contains(clz.getSimpleName());
  }

  private String evalPrimitive(Object obj) {
    String s = String.valueOf(obj);
    if (s.length() > 32) {
      return s.substring(0, 32);
    }
    return s;
  }

  private void evalArray(Object arr, StringBuilder sbd) {
    int sz = Array.getLength(arr);
    if (sz == 0) {
      sbd.append("[]");
      return;
    }
    Class clz = Array.get(arr, 0).getClass();
    if (clz == Byte.class) {
      sbd.append("Byte[").append(sz).append(']');
      return;
    }
    if (isPrimitive(clz)) {
      sbd.append('[');
      int len = Math.min(sz, 10);
      for (int i = 0; i < len; i++) {
        Object obj = Array.get(arr, i);
        if (isPrimitive(obj.getClass())) {
          sbd.append(evalPrimitive(obj));
        } else {
          sbd.append(obj.getClass().getSimpleName()).append(":OBJ");
        }
        sbd.append(',');
      }
      if (sz > 10) {
        sbd.append(",...,len=").append(sz);
      }
      if (sbd.charAt(sbd.length() - 1) == ',') {
        sbd.setCharAt(sbd.length() - 1, ']');
      } else {
        sbd.append(']');
      }
    } else {
      sbd.append("[len=").append(sz).append(']');
    }
  }

  /**
   * 构造时间的显示,带上时分秒的信息,如 2013-06-11 03:14:25
   *
   * @param date 时间
   * @return 字符串表示
   */
  private String formatYmdHis(Date date) {
    Calendar ca = Calendar.getInstance(chinaZone, chinaLocale);
    ca.setTimeInMillis(date.getTime());
    StringBuilder sbd = new StringBuilder();
    sbd.append(ca.get(Calendar.YEAR)).append('-');
    int month = 1 + ca.get(Calendar.MONTH);
    if (month < 10) {
      sbd.append('0');
    }
    sbd.append(month).append('-');
    int day = ca.get(Calendar.DAY_OF_MONTH);
    if (day < 10) {
      sbd.append('0');
    }
    sbd.append(day).append(' ');
    int hour = ca.get(Calendar.HOUR_OF_DAY);
    if (hour < 10) {
      sbd.append('0');
    }
    sbd.append(hour).append(':');
    int minute = ca.get(Calendar.MINUTE);
    if (minute < 10) {
      sbd.append('0');
    }
    sbd.append(minute).append(':');
    int second = ca.get(Calendar.SECOND);
    if (second < 10) {
      sbd.append('0');
    }
    sbd.append(second);
    return sbd.toString();
  }

  protected Object findDefault(Method method) {
    Class clz = method.getReturnType();
    if (clz == String.class) {
      return "";
    } else if (clz == Long.class || clz == Double.class) {
      return 0L;
    } else if (clz == Boolean.class) {
      return Boolean.FALSE;
    } else if (clz.isArray()) {
      return new byte[0];
    } else if (clz.isAssignableFrom(Set.class)) {
      return ImmutableSet.of();
    } else if (clz.isAssignableFrom(List.class)) {
      return ImmutableList.of();
    } else if (clz.isAssignableFrom(Map.class)) {
      return ImmutableMap.of();
    } else {
      return null;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy