jfinal2.2 源碼閱讀日記(一)

jfinal 最大亮點就是零配置極速 WEB (通過對servlet的極薄封裝實現的極速)+ ORM (獨創(chuàng)Db + Record模式,靈活便利)

那極速 WEB 和 獨創(chuàng)Db + Record模式 是怎么實現的呢?

所以看了下jfinal2.2的源碼。

jfinal是通過過濾器攔截服務來實現路由的分發(fā)(web.xml 中配置的filter)。

jfnal 的核心攔截器為:com.jfinal.core.JFinalFilter.java

所以從這個類開始看。

// final 關鍵字修飾,表示不可被繼承,實現了Filter接口

public final class JFinalFilter implements Filter {}

然后實現了 init 初始化方法 在服務啟動過的過程中就由容器調用

現在來看看 init 方法中具體干了哪些事

public void init(FilterConfig filterConfig) throws ServletException {

// 利用反射初始化開發(fā)項目中實現了JfinalConfig類的子類,并且賦值給當前對象的jfinalConfig 變量

createJFinalConfig(filterConfig.getInitParameter("configClass"));


// 然后調用 Jfinal 中的初始化方法

1、配置項目路徑

2、配置 Config 在config中初始化一些項目配置

2.1、配置常量Constant 然后初始化日志使框架日志與系統日期保持一致,默認使用log4j日志,如果項目沒有使用則直接使用jdk日志

2.2、配置路由Route,

2.3、配置插件(Plugin),配置完成后啟動插件,調用插件的start方法。

2.4、配置攔截器(Interceptor),

2.5、配置處理器(Handler)

3、初始化ActionMapping(配置請求路徑對應的控制器對象)

4、初始化處理器,增加ActionHandler()處理器,并且和用戶自定義處理器串聯連接。

5、初始化 render 視圖渲染組件

6、初始化 OreillyCos 文件上傳處理插件

7、初始化 TokenManager(token管理器)

if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false)

throw new RuntimeException("JFinal init error!");

// 獲取jfinal處理器(在 jfinal.init函數中 調用 initHandler 函數 初始化的)

// 在初始化處理器的時候系統會增加一個 ActionHandler() 處理器,然后把這些處理器,和用戶配置的處理器串聯起來了,形成了一個鏈式的結構。

// 最后 jfinal.getHandler(); 返回的是用戶配置的最后一個處理器,然后鏈接的下一個處理器是倒數第二個配置的,一直到 最后一個ActionHandler()

// 所以用戶在每個配置的Handler中都得調用一下 next.handler(...) 函數,如果不調用則最后處理到達不了Controller。

handler = jfinal.getHandler();

// 取出用戶配置的常量

constants = Config.getConstants();

// 編碼設置為用戶在常量中設置的編碼,如果用戶沒有設置,則使用默認的UTF-8編碼

encoding = constants.getEncoding();

// 調用 afterJFinalStart() 函數處理,用戶在配置前自定義處理。

jfinalConfig.afterJFinalStart();

// 設置 contextPath 到此,攔截器的初始化工作完畢,增加jfinal的初始化工作也結束了。

// 啰嗦一句如果項目在tomcat的webapps中不是以ROOT命名的目錄,則contextPath值為用戶的項目目錄名稱

// 否則 contextPath 的值為 /

String contextPath = filterConfig.getServletContext().getContextPath();

contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());

}

接下來,就是攔截器懶覺請求,并且處理請求。

攔截器攔截到的每個請求,都會執(zhí)行doFilter函數,這個函數是Filter接口中規(guī)定的必須實現的函數。

JFinalFilter 類中的 doFilter 函數實現代碼如下,一句一句的來看。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

// 把 ServletRequest 和 ServletResponse 類型的請求與應答強制轉換為HttpServletRequest,和HttpServletResponse

// 這段代碼沒什么就是為了方便使用HttpServletRequest里的一些函數。基本上每個filter 都會這么做。

HttpServletRequest request = (HttpServletRequest)req;

HttpServletResponse response = (HttpServletResponse)res;

// 設置請求編碼,這個編碼就是在初始化函數中,用戶設置的或者系統默認的utf-8編碼。

request.setCharacterEncoding(encoding);

String target = request.getRequestURI(); // 獲取請求 uri

if (contextPathLength != 0)// contextPathLength 不為0則獲取真正的 uri

target = target.substring(contextPathLength);

boolean[] isHandled = {false};? // 默認處理器沒有處理過

try {

// 調用 處理器處理函數(下一篇文章,重點講解)

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

}catch (Exception e) {

if (log.isErrorEnabled()) {

String qs = request.getQueryString();

log.error(qs == null ? target : target + "?" + qs, e);

}

}

// 如果 最后處理到達了。ActionHandler 并且成功處理過了,則isHandled[0]會被標記為true

// 則調用chain.doFilter(request, response); 放行請求,如果用戶在 web.xml 中還配置了其他的過濾器

// 則用戶還會繼續(xù)調用其他過濾器來過濾請求,直到最后返回請求內容給用戶,web容器關閉請求。

// 一個完整的請求就這樣結束了,下一篇內容著重講解 ActionHandler類中的 handle 函數(handler.handle(target, request, response, isHandled))

// 還有一個,isHandled使用數組類型,是因為數組類型使用的是引用傳遞,而boolean使用的是值傳遞。

if (isHandled[0] == false)

chain.doFilter(request, response);

}




最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容