JFinal源碼分析------初始化那些事兒3之ActionMapping

今兒話題,ActionMapping,這個過程主要是創建起你URL訪問使用具體是使用哪兒個Action去處理你的請求,這個過程主要也是也是發生在JFinalFilter初始化過程當中的,下面咱們就具體好好分析分析,ActionMapping他是如何作的,他的內部是如何實現的,上篇博文中咱們就說過,ActionMapping是我認爲最巧妙的地方,如何巧妙,我儘可能用我本身對JFinal的理解去解釋這麼過過程!!先看代碼:java

<!-- lang: java -->

private void initActionMapping() { actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors()); actionMapping.buildActionMapping(); }數組

咱們看到在initActionMapping中是這樣定義的,他主要是作了一下的兩件事情: 一、建立一個ActionMapping的實例,初始化他的routes,和interceptors,具體的做用是什麼,一會詳細說說 二、建立ActionMapping(也就是Action的映射)app

咱們打開ActionMapping發現有以下的類屬性:框架

private static final String SLASH = "/";
private Routes routes;
private Interceptors interceptors;

private final Map<String, Action> mapping = new HashMap<String, Action>();

當咱們的程序執行到這個ActionMapping文件時候,剛剛咱們看到的routes,interceptors屬性在咱們的ActionMapping的構造函數中已經被初始化了,還有一個就是咱們的mapping類屬性,你們能看到,這個是一個Map集合類型,你能猜到他是作什麼的麼??函數

也許你能猜到,其實這個就是咱們裝載咱們Action映射的容器,由於Map這個東西經過Key來獲得Value,(也就是咱們所說的鍵值對),有這個之後,咱們就直接能夠經過咱們的Key去取得咱們先要的Action了,固然,理論是這麼個理論,可是如何實現的話, 咱們就須要經過分析BuildActionMapping的方法去找尋咱們的答案了!!因爲BuildActionMapping中的代碼比較多,那麼我只能選取一些我認爲比較重要的代碼進行解析,有遺漏的歡迎各位不全,不勝感激!!!ui

進入buildActionMapping方法,咱們能夠看到有這樣麼一段代碼: Set<String> excludedMethodName = buildExcludedMethodName(); 這個主要是作啥的?不知道的話 咱們就找到這個方法,而後看看 他作了啥?this

private Set<String> buildExcludedMethodName() { Set<String> excludedMethodName = new HashSet<String>(); Method[] methods = Controller.class.getMethods(); for (Method m : methods) { if (m.getParameterTypes().length == 0) excludedMethodName.add(m.getName()); } return excludedMethodName; }code

喏,看吧 他是想獲取Controller中全部的類的方法,而後經過循環的方式,找出那些個麼有不帶參數的方法,而且減那些不帶參數的方法添加至一個HashSet的集合類型當中。他爲何要作這個操做,以及他的意圖何在?先別急,接着往下看。繼承

當咱們獲取了上述的方法的執行結果以後,咱們看看後面的幾句代碼:路由

//建立一個interceptorBuilder實例,這個不用解釋了吧,搞過JAVA的都會啊 InterceptorBuilder interceptorBuilder = new InterceptorBuilder();

//這個就是獲取全部的Interceptor,而後所有轉換成爲數組而後保存 Interceptor[] defaultInters = interceptors.getInterceptorArray();

//使用interceptorBuilder創建defaultInters 映射 interceptorBuilder.addToInterceptorsMap(defaultInters);

這三個的操做主要是完成對JFinal框架中默認提供的Interceptor進行加載而且映射,步驟基本就是上面說的那些

順便插一句題外話:

public Interceptors add(Interceptor globalInterceptor) { if (globalInterceptor != null) this.interceptorList.add(globalInterceptor); return this; }

還記不記得在咱們的自定義繼承JFinalCofig那個中有一個 public void configInterceptor(Interceptors me) { .... }

這個方法,根據JFinal文檔說要註冊全局的Interceptor要在這裏加,如今看到這個,你應該知道爲何做者要特殊的聲明說 "Global級攔截器要在JFinalConfig.configInterceptor(Interceptors me)中進行配置「(這是做者的原話,有錯誤不要找我)

好了,繼續回到咱們的話題,繼續看代碼: 下面就會有一個循環迭代,代碼以下: for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) { .... } 有沒有看到熟悉的變量了?」routes「,這個咱們剛剛初始化過的,他如今有值了,如今我告訴你這個routes他從哪兒來??他就從下面的方法中來:

public void configRoute(Routes me) { ....(這裏是你配置的路由,對吧??) }

他迭代的就是你這裏面所配置的全部路由信息,而後一個一個的將其迭代出他的值,看到如下代碼 Class<? extends Controller> controllerClass = entry.getValue();

你是否是感受反射又來了,恭喜你 都會搶答了,這個框架中就是大量的使用了Java的反射技術,之前都不知道這個是幹啥用的,如今我終於彷佛好像有點明白了。看到這裏,你可能會問,他爲何或得的值是一個Controller類型的,答案就在這裏: public void configRoute(Routes me) { me.add("/", CommonController.class);(在路由中你是這樣寫的,對吧??) } 因此,在迭代routes的時候,他不獲取Controller,他拿什麼??嘿嘿....

繼續向下(額.....分析這個方法,好累,太多了)

//構建一個ControllerInter數組,用來裝全部的Controller級別的ControllerInter

Interceptor[] controllerInters = interceptorBuilder.buildControllerInterceptors(controllerClass); 喏,Jfinal框架中的另一個級別的攔截器出來了(Controller級別),之後被人問起來講,Controller級別的Interceptor何時被加載建立的,這就是答案啊!!

//獲取某個Controller中的全部的Method,記住這個Controller是咱們本身定義,繼承Controller類的那個Controller(額,好拗口) Method[] methods = controllerClass.getMethods();

剛剛咱們獲得了某一個Controller中的全部方法,而後又開始一個循環,完成對這個獲取這個Controller中的全部方法,而後進行迭代,具體代碼能夠看源碼,這個裏面的代碼太長了,我仍是挑重要的說。

當咱們進入一下的循環之後,主要作了一下操做: 一、獲取method[]中的每個方法名 二、檢查這個方法名是否包含在咱們剛剛獲取的excludedMethodName中,而且還要檢查該方法是否有參數,加入不在excludedMethodName中,而且也沒有任何參數,則進入第3步 三、分別構造一個Action級別的MethodInterceptor和構造一個ActionInterceptors,而且獲取controllerkey 四、看看有沒有使用ActionKey這個註解符,而且對Actionkey註解符中設定的值繼續合理性的驗證,驗證無誤之後,新建一個action實例,而後將該實例放入放入mapping這個類型集合中 五、當咱們的Action中沒有放入Actionkey註解符,就先看看methodname是否是」index「,(咱們知道index這個是Controller中默認的一個方法),若是是,則建立一個Action實例,將這個action實例放入mapping這個集合變量中去。

六、假如咱們在Controller了中沒有使用ActionKey,咱們的方法名稱是index之外的方法,那麼咱們就按照這樣的方式來構造actionkey(固然建立action實例,是和上面相似的,由於他們使用的是一個action建立的方法)

actionkey的格式 String actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;

這個夠清楚了吧,格式就是這樣了。若是之後再出現action沒法訪問,那麼,你就須要從這裏來找緣由了

七、在最後,咱們從mapping中獲取」/「對應的方法,等待着觸發

完整至此,ActionMapping中的映射創建了。哎喲,媽呀 可把我累壞了!!關於ActionMapping的好處,或者是其餘的一些特色,下次再開扒吧!!由於扒源碼真的是個力氣活!!

相關文章
相關標籤/搜索