jfinal 源碼學習

源由

最近閒來無事,順帶看了下jfinal的源碼,如下均爲本身的我的理解,若有錯誤請指定;web

jfinal 使用

  • 在web.xml中配置JfinalFilter 並定義JfinalConfig的類
  • 自定義JfinalConfig 繼承抽象類JfinalConfig並實現抽象方法
  1. public abstract void configConstant(Constants me);
    public abstract void configRoute(Routes me);
    public abstract void configEngine(Engine me);
    public abstract void configPlugin(Plugins me);
    public abstract void configInterceptor(Interceptors me);
    public abstract void configHandler(Handlers me);

     

由上面的幾個方法能夠知道,咱們一會就要跟上面的幾個類打交道了;
Constants : 主要定義項目的常量,好比說是不是開發模式了,上傳下載的根路徑,默認的視圖類型、上傳文件的最大長度、編碼等等;
Routes: 定義訪問路徑與controller的路由關係,能夠新加Routes,如me.add(Routes routes),便於分模塊;基本的me.add(controllerKey,controllerClass,viewPath),若是視圖爲空,則默認爲controllerKey;
Engine : 指定模板引擎,是3.0新增的功能;
Plugins : 添加插件,如數據庫插件、鏈接池插件、緩存插件等,也能夠實現本身的插件;這裏的plugins能夠看做是一個工具類,將多個插件保存在Plugins中的列表中;
Interceptors : 添加全局的攔截器,自定義的攔截器須要實現intercept(Invocation inv)的方法,在inv中能夠獲取controller中的相關內容,具體能夠參考ActionHandler中的handle方法;
Handlers: 添加多個處理器,這裏能夠看做是一個工具類,只是把多個處理器保存到列表中;數據庫

初始化邏輯

JfinalFilter

咱們先看filter初始化的方法,代碼量不多緩存

  1.         createJFinalConfig(filterConfig.getInitParameter("configClass"));
            if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false) {
                throw new RuntimeException("JFinal init error!");
            }
            handler = jfinal.getHandler();
            constants = Config.getConstants();
            encoding = constants.getEncoding();
            jfinalConfig.afterJFinalStart();
            String contextPath = filterConfig.getServletContext().getContextPath();
            contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());

     

咱們一個一個過:
createJFinalConfig : 這個就是在web.xml jfinalFilter中定義的參數:configClass,指向自定義JfinalConfig,會嘗試根據字符串加載類並生成實例,賦值給該filter中的jfinalConfig;
jfinal.init() : 初化jfinal ,大部分的邏輯都在這裏
handler = jfinal.getHandler() : 這一句依賴jfinal的初始化,獲取Handler,你們能夠會問這裏爲何只有一個Handler,我定義的多個處理器哪去了? 想要了解能夠看下Handler的類定義,裏面有一個next的變量,類型也是Handler,沒錯,是一個鏈表,在上一步jfinal初始化過程當中將Handlers中保存的多個handler組裝成了一個鏈表,這裏返回頭,而且在尾部加了一個ActionHandler,用來初始化controller,想了解初始化controller的過程,請參考ActionHandler中的handle的方法;
Config.getConstants(): 在jfinal的初給化方法裏,有初始化Config裏的變量;app

jfinal

從過濾器來看,大部分的初始化碼在jfinal.init(jfinalConfig,servletContext)方法中;
代碼以下:工具

    1. // 設置變量,不用理會
    2. this.servletContext = servletContext;
    3. this.contextPath = servletContext.getContextPath();
    4. // 根據servletContext變量來初始化PathKit工具類的webRootPath;
    5. initPathUtil();
    6. Config.configJFinal(jfinalConfig); // start plugin, init log factory and init engine in this method
    7. constants = Config.getConstants();
    8. initActionMapping();
    9. initHandler();
    10. initRender();
    11. initOreillyCos();
    12. initTokenManager();
    13. return true;

     


Config.configJFinal(jfinalConfig): 將jfinalConfig中定義的內容全配置到Config類中,後面的參數變量均在Config類中定義,很容易看懂,代碼以下:this

  1.         jfinalConfig.configConstant(constants);            initLogFactory();    initEngine();
            jfinalConfig.configRoute(routes);
            jfinalConfig.configEngine(engine);
            jfinalConfig.configPlugin(plugins);                startPlugins();        // very important!!!
            jfinalConfig.configInterceptor(interceptors);
            jfinalConfig.configHandler(handlers);

     

initActionMapping(): 初始化ActionMapping,在這裏完成路由及攔截器的功能,過程以下:
遍歷Config.routes()中的路由關係,根據路由關係中定義的contrllerKey,controllerClass,viewPaht,根據controllerClass利用反射獲取Before()的註解,獲取controller級別的攔截器集合;經過反射獲取全部的方法,再獲取方法上面Before()註解來獲取方法級別的攔截器集合;還能夠獲取routes中的路由級別的攔截器集合及Interceptormanager獲取全局的攔截器集合;
而後將cotrollerKey,actionKey,conrollerClass,method,methodName,ins[],viewPath 構建爲Action,再放入到以actionKey爲key,action爲value的map中;至此,actionMapping初始給完成,直接能夠在jinal中經過actionKey來獲取全部的Action對象;編碼

initHandler(): 初始化處理器
使用HandlerFactory類將handlers中的list中的全部處理器構建爲Handler的鏈表,並在鏈表尾部加入ActionHandler來完成核心功能,其中包括req/resp賦值,ins[]的執行,具體參考該類的handle方法;url

initRender(); // 初始化render
initOreillyCos(); //初始化上傳相關
initTokenManager(); //初始化token緩存,若是在Constants中沒有設置tokenCache,則跳過;spa

至此 ,全部初始化完成 ;插件

業務請求邏輯

jfinal doFilter方法

看完以後發現核心的代碼就一句:

  1. handler.handle(target, request, response, isHandled);

     

若是有自定義處理器,在本身的邏輯處理完成以後,記得加一句: next.handle()來執行下一個控制器;
到最後必然會執行到ActionHandler的handle方法;

ActionHandler handle方法

核心的代碼也就幾句:

  1. //獲取controller對象
    Controller controller = action.getControllerClass().newInstance();
    //初始化controller
    controller.init(request, response, urlPara[0]);
    newInvocation(action, controller).invoke();
    Render render = controller.getRender();
    render.render();

     

inv.invoke(): 執行 當該action有攔截器時,先執行攔截器,ints[i++].interceptor(this);在攔截器內部完成攔截後還執行this.invoke(),一直到全部攔截器都執行完成爲止;
當全部的攔截器都完成以後,this.invoke()實質上就去執行方法:action.getMethod().invoke(controllerInstance,args);
執行完成以後就去獲取Render去作相應的渲染了;

//TODO 雖然大體明白了加載過程,但爲何要這麼用還須要細細體會; //TODO 看下渲染的相關過程 //TODO 看下activeRecord的思想;

相關文章
相關標籤/搜索