因为最近毕业论文导师要求要用一个轻量级的mvc,所有就选了jfinal,初次使用,才疏学浅很多问题不知道怎么个情况,今天抽了点时间读了其源码,写下了一篇笔记,帮助自己理解其原理,大神勿喷哈..
首先找到web.xml.会看见其JFianl如struts一般将其核心控制器作为filter.
1
Web项目启动时候,会加载JFinal的过滤器,并执行其init方法.进入该类,可以看见createJFinalConfig 这个方法会反射得到用户自定义的configClass,并赋给自身的JfinalConfig变量,接下来会通过jfinal.init()方法初始化用户在configClass中配置的相关信息.进入该类后,我们可以看见Config.configJFinal方法,根据此方法
2
3
在这里可以看见用户自定义配置的常量,路由,插件,拦截器,..都在这里进行"配置”,那么我们Config类中的一系列静态常量便有了我们起初的配置值.其中我们的plugins其实是一个List, Routes其实是map.这些在具体的类中都可以体现.
4
在图3中有一步startPlugins方法,进入该方法,可以了解到在这里会拿出用户配置的插件信息,并start(所有插件都必须实现IPlugin接口,并重写其start方法)所有插件, 以启动ActiveRecordPlugin为例,首先会从插件List中拿到这一个实现IPlugin接口的插件,调用start
方法,将我我们之前配置的dataSource作为参数传递给该插件.那我们的DbKit便拥有了我们自己的配置的dataSource,
ActiveRecordPlugin arp = new ActiveRecordPlugin(c3p0Plugin);
DbKit.setDataSource(dataSource);
5
之后便会调用buildTableInfo方法,构建映射在配置文件中add的我们的表信息,根据我们传入的表名和对应的类型,调用doBuildTableInfo 方法,然后再该方法中的TableInfoMapping的tableInfoMap常量表拥有了我们的表的信息.该插件启动完毕.
接下来我们看图2中的几个init方法.跟进initActionMapping,传递进已经做了初始化的Config类中的Routes和Interceptors常量(这两个常量中已经包含了我们在configClass中的相应配置信息) 继续跟进buildActionMapping方法.
6
首先在该方法(图7)中会调用buildExcludeMethodName()方法排除Controll中默认的一些方法,这样一来我们在后续得到的方法将是我们自己定义的Action(controller)中的方法.接着调用getInterceptorArray得到配置的拦截器数组.接着调用interceptorBuilder.addToInterceptorsMap(defaultInters); 方法将会使得interceptorBuilder中的intersMap拥有了我们按照类别区分的全局拦截器.紧接着调用buildControllerInterceptors方法再我们自定义的controller中加上相应的interceptor(
如图8所示,会检查controller中的annotation)
7
8
之后会将我们的自定义的controller(action),及其要执行的方法,拦截器作为map的value以及配置的actionKey(路由)作为map的key加入到Actionmapping中的mapping中,在执行完JFinal类中的一系列init方法之后,我们的Jfinal类中的一些常量便有了我们在configClass类中配置的相关属性.
9
Init方法执行完毕之后,便会执行过滤器的doFilter方法,该方法也会在每一次请求的过程中都会拦截我们请求的URI(即我们form表单的action的值),之后会调用handler调用handle方法,这里的handler其实是我们init方法中的jfinal.init(..)中的initHandler初始化而来,并将其值付给JFinalFilter 的handler,实际上是ActionHandler,跟进这个类的handle方法可以知道他是跟进我们传进来的URI找到对应的action并从action中拿出具体的controller
10
然后init这个controller实际上是将request,response和参数赋值给抽象类Controller,那么继承该类的具体子类便有了从客户端传过来的request和response.!到这里,我们可以在脑海中大致了解Jfinal响应一个请求的过程(首先web容器启动,JFInalFilter初始化我们在configClass中的配置信息,并将其赋给JFInalFilter中的一些必要属性.之后每一一个request到来时,jfinalFilter调用doFilter方法拦截相应请求获得URI,根据我们init过程中初始化的actionMap,以URI为key得到具体的Action.(这个action中包含着我们的controller相关信息),通过action拿到controller并通过init方法将其赋值给Controller类这样一来我们具体的controller便有了操作相应request,response的能力.)
11
然后通过action.getMethod().invoke(controller, NULL_ARGS);执行我们具体controller的具体方法.以上便是jfinal的一个请求过程.
接下来我们再来看其实例中的controller方法, 参见图12
12
Blog这个类其实是我们的POJO,只不过他将操作数据库的相关方法也封装进了Model中以供我们所有实现该类的POJO都具有相应方法.我们跟进一个find方法会发现,在model中,该方法将我们查询得到的结果通过图13中的方式与我们的具体model进行”映射”,因此我们拿到的List中是一个个的对象信息.
13
Render不必多说跟到最后会发现如图14所示,
14
以上便是一个大致的JFinal完成从请求à响应à展现的整个过程,.JFinal就是对servlet进行了一些封装是的我们在操作相关的方法时候更加简便.确实如此,当我们烦透大量的bean,大量的xml文件.大量的set get方法时,我们可以尝试使用JFinal,正如其所说,将节省大量的时间去配你的朋友,家人!