Redis学习记录(二)--使用Jedis连接
标签(空格分隔): javaWEB
在Java环境中连接Redis首选Jedis,因为Jedis封装的特别好,所以连接对于开发者也就变得很简单了,本文主要讲述如何写出优雅的Jedis连接代码.
1.设计模式分析
对于Jedis,有一个连接池JedisPool
,这个连接池管理着程序中的jedis示例,对于单机部署,每一次使用jedis都是去池中取出来连接池,然后再使用他获取我们想要的结果.是不是有点感觉像数据库连接池?那么一般形式代码如下:
public String get(final String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
然而这样写方法多的话,每一个都要如此重复获取,然后执行,然后关闭,返回结果,一套流程,就像模板一样,那么设计模式就可以考虑模板模式.
模板设计模式主要是将通用的逻辑都抽离出来,不通用的逻辑根据实现类的具体策略而执行不同的策略.因为JedisPool
比较类似数据库连接池,因此我们可以参考Spring里的JdbcTemplate
,里面有如下代码:
public T execute(ConnectionCallback action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
//获取连接
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
else {
// Create close-suppressing Connection proxy, also preparing returned Statements.
conToUse = createConnectionProxy(con);
}
//执行策略
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
}
finally {
//关闭连接
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
分析:
代码分为三部分,获取连接,执行策略,关闭释放连接.除了策略,其他都是模板,而策略是一个函数式接口,如下:
public interface ConnectionCallback {
T doInConnection(Connection con) throws SQLException, DataAccessException;
}
那么具体策略就是实现该接口的实现类里面的策略了.这样就很好地做到模板和策略分离,还有一个好处就是函数式接口可以很好地配合java8语法,写出相当优雅的代码.
2.实现
2.1 函数式接口实现
首先参照Spring,实现自己的函数式接口:
比上面多了一个泛型E代表传入参数,这样做的话,就会使得该接口更加具有通用性.
/**
* 模仿Spring ConnectionCallback写的模板接口
* T为操作返回值 E为参数类型
* 配合java8使用,效果更佳
* @author Niu Li
* @date 2016/12/8
*/
public interface WorkCallback {
/**
* 具体执行策略
* @param e 传入参数
* @return 结果
*/
T doWorkCallback(E e);
}
2.2 实现单机版Jedis
实现思路,首先在JedisClientSingle
写一个私有的excute方法,用于实现函数式接口,定义不同策略,代码具体如下:
/**
* 单机版jedis(配置建议都放在依赖注入配置中)
* @author Niu Li
* @date 2016/12/8
*/
public class JedisClientSingle{
/**
* 连接池,建议使用其他工具注入进来
*/
private JedisPool jedisPool;
public String get(final String key) {
return excute(new WorkCallback() {
public String doWorkCallback(Jedis jedis) {
return jedis.get(key);
}
});
}
public String set(final String key, final String value) {
return excute(new WorkCallback() {
public String doWorkCallback(Jedis jedis) {
return jedis.set(key,value);
}
});
}
/**
* 模板方法,很适合提取公共操作
* @param workCallback 处理函数
* @param 返回类型
* @return 结果
*/
private T excute(WorkCallback workCallback) {
Jedis jedis=null;
try {
jedis = jedisPool.getResource();
return workCallback.doWorkCallback(jedis);
} catch (Exception e) {
e.printStackTrace();
}finally {
if (null !=jedis){
jedis.close();
}
}
return null;
}
}
对于jedisPool
的注入的话,Spring中可以如下配置
2.3实现集群版
集群版就简单很多了,只能说Jedis封装的太好了
/**
* jedis集群
* @author Niu Li
* @date 2016/12/8
*/
public class JedisClientCluster {
/**
* 集群控制,建议使用其他工具注入进来
*/
private JedisCluster jedisCluster;
/**
* 其他的直接使用jedisCluster的方法即可
*/
public String get(final String key) {
return jedisCluster.get(key);
}
}
对于jedisCluster
的注入,Spring配置如下: