vert.x
vert.x是一個優秀的,領先的,快速更新的非同步網路服務框架,可以支援tcp/udp/http等多種網路服務,功能強大,效能優越。
vert.x框架支援多種語言,包括java,javascript,groovy,ruby等,在此處採用java語言。
vert.x從來不吝於支援最先進的技術,比如最新的vert.x已經充分支援了java8的各種特性。程式碼風格很接近node.js。簡潔有效。
非同步框架的通病在於回撥地獄,相比於node.js的promise等方案,vert.x也提供了類似的方案,更可以採用協程的方式一勞永逸的解決回撥地獄,同時享受更好的效能。
解析
vert.x預設採用的資料庫連線池是c3p0連線池。由阿里巴巴提供的druid連線池無疑是現在可用的最優秀的免費連線池之一,同時也是為了和其它專案保持同步,以及c3p0的一些坑。決定換用druid連線池。
可是vert.x並沒有提供druid連線池的支援,在官方的文件上對於連線池也是語焉不詳,於是一怒之下clone原始碼來看。
在vert-jdbc-client專案下,我不出意料的找到了這麼一句話:
String DEFAULT_PROVIDER_CLASS = "io.vertx.ext.jdbc.spi.impl.C3P0DataSourceProvider";
複製程式碼
然後在實現類中找到了這麼一段:
String providerClass = config.getString("provider_class");
if (providerClass == null) {
providerClass = DEFAULT_PROVIDER_CLASS;
}
複製程式碼
可見在這裡通過配置provider_class可以指定一個資料來源。那麼下一步就是仿照著C3P0DataSourceProvider來實現一個provider咯。
public interface DataSourceProvider {
int maximumPoolSize(DataSource dataSource, JsonObject config) throws SQLException;
DataSource getDataSource(JsonObject config) throws SQLException;
void close(DataSource dataSource) throws SQLException;
}
複製程式碼
我們需要實現的就是這麼一個介面,其實關鍵的就在於getDataSource這麼一個方法。
實現
druid的資料來源入口是DruidDataSource。我們需要在getDataSource方法中根據引數配置一個資料來源並返回。
druid的配置引數還是很多的,一個個去判斷十分麻煩,這裡採用了一個偷懶的方法,用反射的方式去呼叫set方法來設定引數。
需要注意的是在反射呼叫中,Integer型別和int型別是不能通用的兩個型別,也就是說沒有自動裝箱一類的機制。所以需要對配置中涉及到的幾個基本變數做一下判斷和處理。否則會導致無法正確找到set方法並複製.
@Override
public DataSource getDataSource(JsonObject config) throws SQLException {
DruidDataSource ds = new DruidDataSource();
Method[] methods = DruidDataSource.class.getMethods();
Map<String,Method> methodmap = new HashMap<>();
for (Method method : methods) {
methodmap.put(method.getName(),method);
}
for (Map.Entry<String, Object> entry : config) {
String name = entry.getKey();
if ("provider_class".equals(name)) {
continue;
}
String mName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
try {
Class paramClazz = entry.getValue().getClass();
if(paramClazz.equals(Integer.class)){
paramClazz = int.class;
}else if(paramClazz.equals(Long.class)){
paramClazz = long.class;
}else if(paramClazz.equals(Boolean.class)){
paramClazz = boolean.class;
}
Method method = DruidDataSource.class.getMethod(mName, paramClazz);
method.invoke(ds, entry.getValue());
} catch (NoSuchMethodException e) {
logger.warn("no such method:" + mName);
System.out.println(entry.getValue().getClass());
);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return ds;
}
複製程式碼