写过了三篇的JFINAL框架源码的文章,普遍反响都还不错,谢谢各位OSC同仁们的关心和支持,今后我会更加勤奋的更新博文和相关的技术文章,好了闲话不说了,因为OSC上面的同仁们来看博文的基本是带着问题来的,再打广告会出事的!!进入正题! 记得在第一篇博文的时候就讲过一些关于 初始化的事情 主要的操作初始化的操作都在JfinalFiler里面,再次重申一次就是 Jfinal的入口,今天我们就深入的继续去聊这个初始化的东西。打开JfinalFilter这个文件,看到这句代码: jfinal.init(jfinalConfig, filterConfig.getServletContext() 就是这一句,我们的话题就从这里开始,我们F3走进去看看,可以发现,他从上往下的做了一下的初始化工作:
<!-- lang: java -->
boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
this.servletContext = servletContext;
this.contextPath = servletContext.getContextPath();
initPathUtil();
Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method
constants = Config.getConstants();
initActionMapping();
initHandler();
initRender();
initActiveRecord();
initOreillyCos();
initI18n();
initTokenManager();
return true;
}
我们慢慢的解释一下各个的初始化过程: 1、initPathUtil();这个是路径相关的初始化信息
2、Config.configJFinal(jfinalConfig); 这个是加载我们自定义Config类(也就是我们在我们的项目中的继承JFinalConfig的那个类)中的方法的实现,他的执行顺序在JfinalConfig中指定了,其中的原话是这样的: Config order: configConstant(), configRoute(), configPlugin(), configInterceptor(), configHandler()
大家可以看到,他的顺序就是这样,所以,以后如果亲爱的程序员们还要去想我们的JFinalConfig这个加载顺序是如何的,这个就是答案!!
3、constants = Config.getConstants();这个不多说了 配置常量
4、initActionMapping();这个是初始化Action映射,底层的数据结构是采用HashMap这种数据集合,通过传入的字符串去找对应的Action,我认为这个是JFinal的一个亮点,真的,很多营养都在这里,有时间我们好好分析它是如何的有营养
5、initHandler();//这个是处理器的初始化,具体的下次再说 6、initRender();//今天的重点,准备开扒 7、initActiveRecord();//这个是ActiveRecord的初始化,这个是我们最 8、initOreillyCos();//这个干嘛的。还在摸索,据推测,应该与文件上传相关的东西 9、initI18n();//国际化 不用多讲了吧 10、initTokenManager();//这个不知道怎么说....求专业名词
initRender()
我们F3到initRender()中,我们可以看到以下的代码: private void initRender() { RenderFactory renderFactory = RenderFactory.me(); renderFactory.init(constants, servletContext); }
可以看到,在Jfinal中的Render的产生是通过工厂模式来生成的,第一句就是通过RenderFactory的me方法来生成的,其定义如下: private static final RenderFactory me = new RenderFactory(); 这也就是说在我们的JFinal框架被加载的时候, 我们就能够得到一个RenderFactory对象实例,这样的话 我们就能够使用这个对象实例进行初始化了。
下面 我们来看看renderFactory.init(constants, servletContext)中有啥?
public void init(Constants constants, ServletContext servletContext) { this.constants = constants; RenderFactory.servletContext = servletContext;
// init Render
Render.init(constants.getEncoding(), constants.getDevMode());
initFreeMarkerRender(servletContext);
initVelocityRender(servletContext);
initFileRender(servletContext);
// create mainRenderFactory
if (mainRenderFactory == null) {
ViewType defaultViewType = constants.getViewType();
if (defaultViewType == ViewType.FREE_MARKER)
mainRenderFactory = new FreeMarkerRenderFactory();
else if (defaultViewType == ViewType.JSP)
mainRenderFactory = new JspRenderFactory();
else if (defaultViewType == ViewType.VELOCITY)
mainRenderFactory = new VelocityRenderFactory();
else
throw new RuntimeException("View Type can not be null.");
}
// create errorRenderFactory
if (errorRenderFactory == null) {
errorRenderFactory = new ErrorRenderFactory();
}
}
这里面主要有下面的事情发生了: 1、Render.init() 在这里主要是做编码的设置和开发模式的设置 2、初始化Freemark,Velocity,File 3、通过获取视图的值来选择我们随用的视图种类,如,你是使用Freemark,还是使用JSP,还是使用VELOCITY。也可以看出,JFINAL是支持我们刚刚提到的三种是视图的,至于你喜欢哪个,可以再Constant里面设置
当我们或得了我么的视图类型的以后 我们可以进入到相应的RenderFactory的中去看看他还为我们做了些啥。已JSPRenderFactory为例: 在RenderFactory中,他定义了一下的代码:
private static final class JspRenderFactory implements IMainRenderFactory { public Render getRender(String view) { return new JspRender(view); } public String getViewExtension() { return ".jsp"; } } 可以看到,其中所有的XxxRenderFactory都继承了一个IMainRenderFactory接口,这里面的两个方法都是需要他在被继承的类中做实现的,这两个方法是: Render getRender(String view); String getViewExtension(); 这两个方法的作用是:一个是用来获取Render的实例,一个是用来获取视图的后缀名。 回到我们的JspRenderFactory 中,我们可以看到在实现第一个方法的时候,他放回的时候一个JspRender,实现第二个方法的时候,获取的后缀名是.jsp,好了,这样的话就初始化好了我们Render类型,在调用的时候就能够根据对应的设置来做Render对应的视图类型了
view参数就是Controller中传过来的我们制定的那个跳转的视图,那么这个view在什么时候下使用了??这里就简单说一下 在我们刚刚的JspRender中有一下代码: public void render() { try { if (isSupportActiveRecord) supportActiveRecord(request); request.getRequestDispatcher(view).forward(request, response); } catch (Exception e) { throw new RenderException(e); } }
大家有没有看到熟悉的,大概能够猜到了吧,我们在我们出来Action的时候,肯定会有一步调用到这个 然后通过 request.getRequestDispatcher(view).forward(request, response); 去跳转,简单的就是这么样的,具体如何工作的 我们下次再说!!!
Render()就初始化就是大概就是这样....