上周末应好友之邀写了一个 JF 多租户的 demo。在编写租户ActiveRecordPlugin时出现一个小灵感,以前我们自己使用的是一个模板数据库,用来做 Db启动 映射表字段类关系。
(PS:以前JF低版本有些方法未开放,也有写过一个插件https://jfinal.com/share/2508 )。
在 JF 高版本中这些set 方法已经开放可调用了。废话不多说了,上码:
还是官网的JFinal demo for maven 5.0.0 https://jfinal.com/download/now?file=jfinal_demo_for_maven-5.0.0.zip
1、自定义 mapping_kit_template.jf 模板:
package #(mappingKitPackageName);
import com.jfinal.plugin.activerecord.*;
/**
* Generated by JFinal, do not modify this file.
* <pre>
* Example:
* public void configPlugin(Plugins me) {
* arp = new ActiveRecordPlugin(new NullDataSource(){
* public Connection getConnection() throws SQLException {
* return dbp.getDataSource().getConnection();
* }
* });
* #(mappingKitClassName).mapping(arp);
* me.add(arp);
* }
* </pre>
*/
@SuppressWarnings("unchecked")
public class #(mappingKitClassName) {
public static void mapping(ActiveRecordPlugin arp) {
Config config = arp.getConfig();
#for (tableMeta : tableMetas)
#(tableMeta.name)(config);
#end
}
#for (tableMeta : tableMetas)
private static void #(tableMeta.name)(Config config) {
#if (tableMeta.primaryKey.contains(","))
// Composite Primary Key order: #(tableMeta.primaryKey)
#end
Table t = new Table("#(tableMeta.name)", "#(tableMeta.primaryKey)", #(tableMeta.modelName).class);
t.setColumnTypeMap(config.getContainerFactory().getAttrsMap());
#for(cm : tableMeta.columnMetas)
t.setColumnType("#(cm.name)", #(cm.javaType).class);
#end
config(config, t);
}
#end
private static void config(Config config, Table t) {
TableMapping.me().putTable(t);
CPI.addModelToConfigMapping(t.getModelClass(), config);
}
}2、修改 _JFinalDemoGenerator.java 设置自定义模板 setMappingKitTemplate
// 自定义 _MappingKit 模板 支持免启动JF映射ColumnType
generator.setMappingKitTemplate("/generator/mapping_kit_template.jf");
// 生成
generator.generate();3、配置ActiveRecordPlugin 的方式:JFinalConfig 子类DemoConfig:
public void configPlugin(Plugins me) {
DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost/db_name", "userName", "password");
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(new NullDataSource(){
public Connection getConnection() throws SQLException {
return dp.getDataSource().getConnection();
}
});
// 所有映射在 MappingKit 中自动化搞定
_MappingKit.mapping(arp);
me.add(arp);
}可以看到 以前是 new ActiveRecordPlugin(dp) , 现在是用new NullDataSource包裹了一下。
4、运行 _JFinalDemoGenerator.java 生成新的 _MappingKit 类代码,看效果:
...
@SuppressWarnings("unchecked")
public class _MappingKit {
public static void mapping(ActiveRecordPlugin arp) {
Config config = arp.getConfig();
blog(config);
}
private static void blog(Config config) {
Table t = new Table("blog", "id", Blog.class);
t.setColumnTypeMap(config.getContainerFactory().getAttrsMap());
t.setColumnType("id", java.lang.Integer.class);
t.setColumnType("title", java.lang.String.class);
t.setColumnType("content", java.lang.String.class);
config(config, t);
}
private static void config(Config config, Table t) {
TableMapping.me().putTable(t);
CPI.addModelToConfigMapping(t.getModelClass(), config);
}
}可以看到 以前的 arp.addMapping("blog", "id", Blog.class); 被改为了调用 blog(config);方法
(也可把该代码生成到 BlogBaseModel中去,_MappingKit调用类方法,这个看自己喜好了)。
该方法把从数据库查询字段关系类映射到setColumnType,变为了 Java 执行setColumnType 字段与类关系代码。
好处很多,比如启动项目更快了,git代码仓库也有字段记录了,阅读代码更明晰了。。。
PS:https://jfinal.com/app/10057 官网Demo改造的多租户模式代码示例
aifei 也用了这种方式,启动速度更快了