一,通过函数指针避免try-cath的书写
使用jedis灵活可靠,而且用微不足道的序列化消耗提高开发效率。
首先看一段try-with-resoure风格的jedis片,这种方式jedis会在cath(Excepiton e)或者try代码结束后调用jedis.close()方法
try (Jedis jedis = new Jedis("119.29.111.111", 6379);) {
jedis.select(3);// 选择数据库
// 增
jedis.set("gao", "tia n");// 每次都会覆盖旧的key
// 查
Logger.getGlobal().info(jedis.get("a"));
} catch (Exception e) {
e.printStackTrace();
}
为了减少redis创建和销毁连接的消耗,我们使用jedis池
JedisPool pool = new JedisPool(poolConfig, "119.29.111.111", 6379, 0, "foobared", 3);
try (Jedis jedis = pool.getResource()) {
} catch (Exception e) {
e.printStackTrace();
}
pool.close();
注意jedis的close方法,会尝试还给自己的jedis池,而不是关闭链接,这里不再赘述。
这样每次try是不是很不方便?
我们可以用一个函数指针,来描述给我一个Jedis对象,我对他进行某些操作,然后返回给我某个类型的值来传入到这个try-with-resource的代码片段里
定义函数指针:
public interface JedisCallBack {
T doInRedis(Jedis jedis) throws DataAccessException;
}
定义一个jedis池的包装类
public class JedisPoolHandler {
private JedisPool pool;
...
public T excute(JedisCallBack action){
try (Jedis jedis = pool.getResource()){
return action.doInRedis(jedis);
} catch (Exception e) {
LogCore.BASE.error("jedisHandler err", e);
return null;
}
}
}
我们接下来看看使用
long num = handler.excute((jedis) -> jedis.incr(name));
是不是很方便?!
二,配置文件和bean的注入
之前的jedis.property
jedis.database=0
jedis.host=localhost
jedis.password=foobared
jedis.port=6379
jedis.timeout=0
java文件
public class JedisConfigBase {
private int database;
private String host;
private String password;
private int port;
private int timeout;
...get,set's methods
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
@Order(value = 1)
@Component
public class JedisPoolHandlerInstances implements CommandLineRunner{
@Component //外部tomcat不可以配置为component,嵌入式tomcat需要此注解
@ConfigurationProperties(prefix="jedis",locations="classpath:jedis.properties")
public static class JedisConfigStats extends JedisConfigBase{}
@Autowired
JedisConfigStats stats_jedis_cf;
private static JedisPoolHandler STATS_HANDLER;
public static JedisPoolHandler getSTATSHandler(){
return STATS_HANDLER;
}
@Override
public void run(String... args) throws Exception {
STATS_HANDLER = new JedisPoolHandler(stats_jedis_cf);
}
}
这样写每次都需要getSTATSHander(),不能直接用静态变量STATAS_HANDER,因为别的类的属性在定义时引用的时候,这个对象还没有被Spring注入
但是这样,依然很丑陋。
三,我们重新梳理一下
jedis.properties文件
jedis.database=10
jedis.host=localhost
jedis.auth=foobared
jedis.port=6377
jedis.timeout=0
public interface JedisCallBack {
T doInRedis(Jedis jedis) throws DataAccessException;
}
public class JedisPoolTemplate {
private JedisPool pool;
public JedisPoolTemplate(String host, int port, int timeout, String psw, int database) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
pool = new JedisPool(poolConfig, host, port, timeout, psw, database);
}
public T excute(JedisCallBack action){
try (Jedis jedis = pool.getResource()){
return action.doInRedis(jedis);
} catch (Exception e) {
LogCore.BASE.error("jedisHandler err", e);
return null;
}
}
}
@Configuration
@PropertySource("classpath:jedis.properties")
public class JedisPoolConfig {
@Bean
JedisPoolTemplate getJedisPoolTemplate(
@Value("${jedis.host}") String host,
@Value("${jedis.port}") int port,
@Value("${jedis.auth}") String auth,
@Value("${jedis.timeout}") int timeout,
@Value("${jedis.database}") int database
) {
JedisPoolTemplate template = new JedisPoolTemplate(host, port, timeout, auth, database);
return template;
}
}
使用方法
@Autowired
JedisPoolTemplate jedisTemplate;
public long incrBy(String name, long value) {
return jedisTemplate.excute((jedis) -> jedis.incrBy(name, value));
}
public Long zadd(String key, double score, String value) {
return jedisTemplate.excute((jedis) -> jedis.zadd(key, score, value));
}