做WEB应用,假如你没有任何对数据库的操作,那么你的应用将一无事处,为什么这么说,因为你所有的业务数据没有办法存储,所以数据库在WEB应用当中是占有相当重要的地位的.
那么在Jfinal中,WEB应用他应该如何去实现的了?在实现这个过程当中,我们应该注意些什么样的细节了.在这些细节当中,又会有那些个坑在等着我们了?
为了能让我们更加好的去处理Jfinal与数据库之间的关系,我们今儿有必要去看看关于这方面的一些个事情.
我们如果使用过SSH的话,应该对那些个XML文件配置会比较熟悉,比如Spring的类实例的注入,比如Hibernate的实体映射什么的.同样的,在Jfinal中也一样,虽然我们不用设置那么多的选项,也不用去写那些个XML文件,但是我们还是要做一些个必要的配置操作的.
首先,我们要解决的就是数据库连接的问题,如果有使用过JDBC的同学们应该知道,我们与数据库操作的第一步就是使用Connection来连接我们需要的数据库,当然这些都是原理上的东西,后来我们使用框架的时候又接触了连接池,不管使用什么原理去链接数据库,我们都需要牢牢的记住一点,我们需要配置数据库的地址和数据库用户名和密码.
在DEMO中我们应该看到一个在”WEB-INF”下面的a_little_config.txt文件,其实这个就是我们数据库的一些个配置,只不过是用这样的形式来表演而已。
我们就从这个地方开始分析,在Jfinal使用数据的时候,是在什么时候进行加载数据库的配置,又在什么情况下进行实体和表进行对应的。
a_little_config.txt加载的时机
这个我觉得不用过多的说明了吧,猜都能猜到是在容器启动的时候进行加载的。所以今天这个不是我们讨论的重点,重点在于,他怎么加载的,以什么样的形式加载,在内存中他是以什么样的形式去表现的等等。
点开我们的Jfinal.java,找到
Config.configJFinal(jfinalConfig);
看到这个方法了吧,在这个方法里面,就把我们需要设置的所有Jfinal相关配置都做了一次设置。因为这个JfinalFilter也算是一个过滤器,他在容器启动的时候,他只会去执行一次,这样的操作,所以,他的作用是不是有点和WEB.xml中的作用类似?这下你是不是应该知道点什么东西了?为神马JFinal要把这个Config对象中设立一个类似ConfigPlugin的方法,就是为了让你能够拓展你自己的Plugin,那你会问这样和在配置WEB.Xml中的有什么区别么?额,因为你在xml中配置了这样的配置:
<filter-mapping>
<filter-name>jfinal</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
因为你的url-pattern是我们看到的这个,你如果在再这个地方陪其他的东西,可能会出现冲突,具体什么冲突,我没有试过,所以,假如你想要拓展你自己的Plugin,我建议你还是自己写一个,完了再Config中进行加载。
回到我们讨论的话题:
在我们进入了Config对象的时候,我们可以看到
jfinalConfig.configConstant(constants);
jfinalConfig,此时的jfinalConfig就会调用你项目中的那个Config对象,然后进行多态调用。
你还记得你在你自己项目中的配置中有这么一句话么,
loadPropertyFile("a_little_config.txt");
这个就是去调用你的那个数据库的配置文件。
F3进入这个方法,然后你看看都有啥
public Properties loadPropertyFile(String file) {
...
InputStream inputStream = null;
String fullFile; // String fullFile = PathUtil.getWebRootPath() + file;
if (file.startsWith(File.separator))
fullFile = PathKit.getWebRootPath() + File.separator + "WEB-INF" + file;
else
fullFile = PathKit.getWebRootPath() + File.separator + "WEB-INF" + File.separator + file;
...
}
看到这个函数了吧,他返回的是用Properties对象,也就是说,在内存当中,他是以这样的方式去存的,不知道Properties对象的同学请自行查看JavaSE的API,在这就不多说了
还有要说的就是,为什么这个配置文件需要放在WEB-INF当中,因为他代码就是这么写的,然后你照着做就好了!
看完这个以后,我们看看
public void configPlugin(Plugins me) {
C3p0Plugin c3p0Plugin = new C3p0Plugin(getProperty("jdbcUrl"), getProperty("user"), getProperty("password").trim());
me.add(c3p0Plugin);
// 配置ActiveRecord插件
ActiveRecordPlugin arp = new ActiveRecordPlugin(c3p0Plugin);
me.add(arp);
…
}
看到了吧,在Jfinal中,数据库的链接是由这些个数据库连接池组件来提供的,为甚么要这样,提高性能,减少建立数据库连接的时间,因为我们知道,数据库连接的建立是很消耗资源的。然后我们设置这个数据库连接池的一些个基本配置,什么URL,什么用户名,什么密码之类的;
在我们的数据库连接池建立好以后,我们就可以为ActiveRecord提供这些建立好的资源,然后就去建立数据库的链接什么的。
到此,我们的第一步就做好了!数据库的链接池已经有了!那么现在我们看第二部,表和实体映射,也就是我们平时所说的ORM,嘿嘿…
看如下代码:
public ActiveRecordPlugin addMapping(String tableName, String primaryKey, Class<? extends Model<?>> modelClass) {
tableMappings.add(new TableInfo(tableName, primaryKey, modelClass));
return this;
}
AddMapping,就是添加实体与表的映射关系,其实你看就明白,这个ORM对应的关系是存储在TableInfo中的。
通过我们自己配置ORM,我们就得到了TableInfo实例,然后所有的Plugin都是去实现IPLUGIN的start()方法,去按照预定的方式去启动相应的过程。
就那我们这个ActiveRecordMapping来说,在我们添加了ORM这关系以后,他肯定会去执行start()方法。这样在我们容器启动的过程,我们就完成了实体和表的映射关系。
不信?有代码为证…
public boolean start() {
if (isStarted)
return true;
if (dataSourceProvider != null)
dataSource = dataSourceProvider.getDataSource();
if (dataSource == null)
throw new RuntimeException("ActiveRecord start error: ActiveRecordPlugin need DataSource or DataSourceProvider");
DbKit.setDataSource(dataSource);
isStarted = true;
return TableInfoBuilder.buildTableInfo(tableMappings);
}
上面的代码告诉我们,ActiveRecord启动的过程中,是TableInfoBuilder类来为提供建立表-实体映射提供动力的。
至此 我们这个数据库链接建立和数据库ORM建立的过程就算完成了!欢迎关注…后期将继续深入挖掘框架背后的故事。