博客標題

無論是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的入口。從代碼層面說,還有幾點須要改進

  1. 去掉 createJFinalConfig,放入Jfinal主類中感受比較好,並在init中調用

  2.  initLogger在Config類中被調用,Config被Jfinal調用,而JFinalFilter自己又調用Jfinal中的方法,

    造成的相互依賴,感受不太好

  3. init方法內容是幾個不相關的內容,最好分出來。

  4.  下面的代碼段,放在init中沒有意義,自己Constants是靜態類,並且僅使用一次,在使用的地方直接

     Config.getConstants().getEncoding()便可,或者在使用該變量的方法開始的時候

          encoding=Config.getConstants().getEncoding();

  constants = Config.getConstants();

  encoding = constants.getEncoding();
相關文章
相關標籤/搜索