博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jfinal-Plugin源码解读
阅读量:5032 次
发布时间:2019-06-12

本文共 7731 字,大约阅读时间需要 25 分钟。

PS:cnxieyang@163.com/xieyang@e6yun.com

本文就Jfinal-plugin的源码进行分析和解读

  • Plugin继承及实现关系类图如下,常用的是Iplugin的三个集成类:DruidPlugin、RedisPlugin、ActiveRecordPlugin,下文就父类及3个实现类做解读
  • IPlugin详解
    IPlugin为Jfinal插件实现类的接口,提供了两个抽象的方法:boolean start(); boolean stop();供子类实现,Jfinal在加载时,调用实现类的start()方法启动插件,所谓插件是将某个业务模块进行了封装,如redis、dbcp等。定义方法如下
    boolean start();	boolean stop();  
  • IDataSourceProvider详解
    IDataSourceProvider提供获取DataSource的方法,其本身为接口,凡是与数据库相关的插件都可以实现IDataSourceProvider接口,接口中的方法如下图
    DataSource getDataSource();
  • 如何加载自定义插件
    1.在JFinalConfig实现类的configPlugin(Plugins me)方法中创建对象,将启动逻辑写到插件继承类的start方法中
    2.在JFinal的init-->Config.configJFinal(jfinalConfig)-->startPlugins()中完成对插件的start方法的调用,加载插件成功
  • RedisPlugin源码解读(不深入到redis,仅读取到Jredis对象的获取,其余部分在后续的redis章节讲解)
    PS:此处基本上没有难度,自行研究即可
    包括:主缓存、redis缓存的缓存、缓存方法的封装
  • DruidPlugin源码解读(仅读取到数据库连接的获取,其余部分在后续得Druid高级使用模块讲解)
    DruidPlugin主要是多Druid的DruidDataSource注入了相关的参数变量,不做分析
  • ActiveRecordPlugin源码
    ActiveRecordPlugin是Jfinal引入的持久层的新思路,下文重点讲解什么是ActiveRecordPlugin、用途、高级使用等
    ActiveRecordPlugin实现的是DB+ActiveRecord模式
    /**     * 配置插件     */    public void configPlugin(Plugins me) {        // 配置C3p0数据库连接池插件        DruidPlugin druidPlugin = createDruidPlugin();        me.add(druidPlugin);                // 配置ActiveRecord插件,需要传入IDataSourceProvider dataSourceProvider,druidPlugin刚刚好是IDataSourceProvider的子类         //A1:初始化ActiveRecordPlugin
    ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin); //A2:所有映射在中自动化搞定,加载映射关系         arp.addMapping("blog", "id", Blog.class);         me.add(arp);     }

     

  • ActiveRecordPlugin如何初始化 1.调用下方构造
    public ActiveRecordPlugin(IDataSourceProvider dataSourceProvider) {        this(DbKit.MAIN_CONFIG_NAME, dataSourceProvider);    }

     2.继续调用ActiveRecordPlugin(String configName, IDataSourceProvider dataSourceProvider)构造,如下

     

    public ActiveRecordPlugin(String configName, IDataSourceProvider dataSourceProvider) {        this(configName, dataSourceProvider, DbKit.DEFAULT_TRANSACTION_LEVEL);    }

    3.传入事务的级别后再调用构造,如下

    public ActiveRecordPlugin(String configName, IDataSourceProvider dataSourceProvider, int transactionLevel) {        if (StrKit.isBlank(configName)) {            throw new IllegalArgumentException("configName can not be blank");        }        if (dataSourceProvider == null) {            throw new IllegalArgumentException("dataSourceProvider can not be null");        }         //IDataSourceProvider 的对象赋值
    this.dataSourceProvider = dataSourceProvider;        //赋值当前对象的config属性的属性值,PS代码省略 this.config = new Config(configName, null, transactionLevel); }

     

  • 模型与表明如何映射
    JFinal为我们提供重载的两个方法,实现对数据表与实体模型的映射,如下放所示
    //带有主键,主键以逗号隔开    public ActiveRecordPlugin addMapping(String tableName, String primaryKey, Class
    > modelClass) { tableList.add(new Table(tableName, primaryKey, modelClass)); return this; } //不带主键 public ActiveRecordPlugin addMapping(String tableName, Class
    > modelClass) { tableList.add(new Table(tableName, modelClass)); return this; }

    1.有主键的Table的初始化

    public Table(String name, String primaryKey, Class
    > modelClass) { if (StrKit.isBlank(name)) throw new IllegalArgumentException("Table name can not be blank."); if (StrKit.isBlank(primaryKey)) throw new IllegalArgumentException("Primary key can not be blank."); if (modelClass == null) throw new IllegalArgumentException("Model class can not be null."); this.name = name.trim(); setPrimaryKey(primaryKey.trim()); this.modelClass = modelClass; }
    //将以逗号隔开的主键拆分数数组并赋值给primaryKey对象 void setPrimaryKey(String primaryKey) {String[] arr = primaryKey.split(",");for (int i=0; i

    2.无主键的Table的初始化

    public Table(String name, Class
    > modelClass) { if (StrKit.isBlank(name)) throw new IllegalArgumentException("Table name can not be blank."); if (modelClass == null) throw new IllegalArgumentException("Model class can not be null."); this.name = name.trim(); this.modelClass = modelClass; }

    3.存储Table关系到List中

    ps:ActiveRecordPlugin类中提供了私有集合private List<Table> tableList = new ArrayList<Table>();用来存储table映射到List中

  • ActiveRecordPlugin加载并初始化映射关系
    PS:插件的启动在JFinal启动源码解读博客章节做了详细介绍<http://www.cnblogs.com/cnxieyang/p/7236734.html>请点击参照。
        循坏调用所有插件的Start方法,完成插件的启动,ActiveRecordPlugin的start启动方法如下,下方对所有实现做详细介绍
    public boolean start() {		if (isStarted) {			return true;		}		if (config.dataSource == null && dataSourceProvider != null) {			config.dataSource = dataSourceProvider.getDataSource();		}		if (config.dataSource == null) {			throw new RuntimeException("ActiveRecord start error: ActiveRecordPlugin need DataSource or DataSourceProvider");		}				config.sqlKit.parseSqlTemplate();		//C1:构建映射		new TableBuilder().build(tableList, config);                 //添加配置
    DbKit.addConfig(config);		isStarted = true;		return true;	}

    1.C1:构建映射调用build方法

    void build(List
    tableList, Config config) { // 支持 useAsDataTransfer(...) 中的 arp.start() 正常运作 if (config.dataSource instanceof NullDataSource) { return ; } Table temp = null; Connection conn = null; try { conn = config.dataSource.getConnection(); TableMapping tableMapping = TableMapping.me(); for (Table table : tableList) { temp = table; //C11:构建 doBuild(table, conn, config); //Map集合中存储映射关系 tableMapping.putTable(table); DbKit.addModelToConfigMapping(table.getModelClass(), config); } } catch (Exception e) { if (temp != null) { System.err.println("Can not create Table object, maybe the table " + temp.getName() + " is not exists."); } throw new ActiveRecordException(e); } finally { config.close(conn); } }

    C11:实现如下

    @SuppressWarnings("unchecked")    private void doBuild(Table table, Connection conn, Config config) throws SQLException {        table.setColumnTypeMap(config.containerFactory.getAttrsMap());        if (table.getPrimaryKey() == null) {            table.setPrimaryKey(config.dialect.getDefaultPrimaryKey());        }        //构建查询数据库字段的sql        String sql = config.dialect.forTableBuilderDoBuild(table.getName());        Statement stm = conn.createStatement();        ResultSet rs = stm.executeQuery(sql);        ResultSetMetaData rsmd = rs.getMetaData();        //遍历数据表字段,将数据表字段类型映射成JAVA类型,并存储到Table对象中        for (int i=1; i<=rsmd.getColumnCount(); i++) {            String colName = rsmd.getColumnName(i);            String colClassName = rsmd.getColumnClassName(i);                        Class
    clazz = javaType.getType(colClassName); if (clazz != null) { table.setColumnType(colName, clazz); } else { int type = rsmd.getColumnType(i); if (type == Types.BINARY || type == Types.VARBINARY || type == Types.BLOB) { table.setColumnType(colName, byte[].class); } else if (type == Types.CLOB || type == Types.NCLOB) { table.setColumnType(colName, String.class); } else { table.setColumnType(colName, String.class); } // core.TypeConverter // throw new RuntimeException("You've got new type to mapping. Please add code in " + TableBuilder.class.getName() + ". The ColumnClassName can't be mapped: " + colClassName); } } rs.close(); stm.close(); }

     

    备注:以上完成了ActiveRecordPlugin的初始化,后续详解如何使用Db+ActiveRecord的方式加载或者写入数据
    PS:时间不早了,休息了。。。

转载于:https://www.cnblogs.com/cnxieyang/p/Jfinal-plugin.html

你可能感兴趣的文章
oracle直接读写ms sqlserver数据库(二)配置透明网关
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
Oracle composite index column ordering
查看>>
ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表
查看>>
kaggle竞赛
查看>>
区块链入门教程
查看>>
域 搭建OU 组织单元
查看>>
npm常用命令
查看>>
南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询...
查看>>
[置顶] 细说Cookies
查看>>
[wp7软件]wp7~~新闻资讯,阅读软件下载大全! 集合贴~~~
查看>>
生成指定位数随机数的方法
查看>>
java的垃圾回收
查看>>
Essential C++学习笔记
查看>>
python+selenium进行简单验证码获取
查看>>
where,having与 group by连用的区别
查看>>
【MySQL】MySQL锁和隔离级别浅析二 之 INSERT
查看>>
Oracle T4-2 使用ILOM CLI升级Firmware
查看>>
4.14上午
查看>>
数据分析 -- 白话一下什么是决策树模型(转载)
查看>>