無論是Stuct2仍是Spring MVC,都是經過在Web.xml裏面加入filter,使得Web服務器啓動時加載它。Jfinal也是。java
filter自己是對Web全部請求的過濾。在 Web服務器啓動的時候會加載Filter-class,利用這點Jfinal也就加載起來了。數組
<filter> <filter-name>jfinal</filter-name> <filter-class>com.jfinal.core.JFinalFilter</filter-class> <init-param> <param-name>configClass</param-name></init-param> </filter> <filter-mapping> <filter-name>jfinal</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這裏的Filter-class是com.jfinal.core.JFinalFilter,因此咱們要從它開始看起。服務器
public final class JFinalFilter implements Filter
從定義中能夠看出,JFinal是實現了Filter接口app
Filter接口裏面有三個主要的方法:編碼
public void init(FilterConfig filterConfig); public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain); public void destroy();
這是Java自己的東西,Jfinal是對他的實現。url
在init方法中Jfinal完成了自身的初始化。code
public void init(FilterConfig filterConfig) throws ServletException { //實例化 ConfigClass createJFinalConfig(filterConfig.getInitParameter("configClass")); //進行最主要的Jfinal初始化(疑問:爲何不把ConfigClass也放到Jfinal.init中來,這樣代碼更容易理解) if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false) throw new RuntimeException("JFinal init error!"); //得到Jfinal初始化後的對象。 handler = jfinal.getHandler(); //得到配置的編碼信息,(疑問:應該直接默認UTF-8,此處真是畫蛇添足) constants = Config.getConstants(); encoding = constants.getEncoding(); jfinalConfig.afterJFinalStart(); //解析路徑的時候須要把前面的主機名,協議名去掉,好比 //此處contextPath 是http://127.0.0.1,那麼之後獲得http://127.0.0.1/helloworld時, //能夠根據contextPathLength把http://127.0.0.1截掉,這樣獲得helloworld, //而後根據helloworld進行映射controller方法 String contextPath = filterConfig.getServletContext().getContextPath(); contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length()); }
在doFilter中Jfinal調用真正的處理。server
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //傳過來的ServletRequest和 ServletResponse 進行類型轉換HttpServletRequest,HttpServletResponse //爲何進行類型轉換: HttpServletRequest和ServletRequest都是接口 //HttpServletRequest繼承自ServletRequest //HttpServletRequest比ServletRequest多了一些針對於Http協議的方法。 //如getHeader(String name),getMethod(),getSession() 等等。 HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; request.setCharacterEncoding(encoding); String target = request.getRequestURI(); if (contextPathLength != 0) 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); } } if (isHandled[0] == false) chain.doFilter(request, response); }
在destroy只是留下了擴展接口,沒有實際內容。xml
在整個JFinalFilter類中,還有兩個方法對象
private void createJFinalConfig(String configClass) static void initLogger()
createJFinalConfig使用了反射,實例化了ConfigClass,
ConfigClass就是在<param-value>com.demo.common.DemoConfig</param-value>配置的類。
createJFinalConfig裏面的方法是比較common的方法,爲何沒有放在util裏面,很奇怪。
總結:
JFinalFilter是直接和Web server耦合的類,是Jfinal的入口。從代碼層面說,還有幾點須要改進
去掉 createJFinalConfig,放入Jfinal主類中感受比較好,並在init中調用
initLogger在Config類中被調用,Config被Jfinal調用,而JFinalFilter自己又調用Jfinal中的方法,
造成的相互依賴,感受不太好
init方法內容是幾個不相關的內容,最好分出來。
下面的代碼段,放在init中沒有意義,自己Constants是靜態類,並且僅使用一次,在使用的地方直接
Config.getConstants().getEncoding()便可,或者在使用該變量的方法開始的時候
encoding=Config.getConstants().getEncoding();
constants = Config.getConstants(); encoding = constants.getEncoding();