1. 程式人生 > >JFinal Handler原始碼解析——從配置到工作原理

JFinal Handler原始碼解析——從配置到工作原理

JFinal頂層是一個Handler鏈是責任鏈模式的一個變種,會攔截到所有請求,包括靜態資源請求。

首先、我們來看看Handler的配置,我們在JFinal的Config中可用來配置自定義的Handler。

@Override
public void configHandler(Handlers me) {
    me.add(new FakeStaticHandler());
}

在這個新增JFinal內建或者我們自己的Handler,在Handlers中有一個ArrayList來儲存她們。

final public class Handlers {

    private
final List handlerList = new ArrayList(); public Handlers add(Handler handler) { if (handler != null) handlerList.add(handler); return this; } public List getHandlerList() { return handlerList; } }

下面、是Handler的初始化,在專案啟動JFinalFilter.init初始化時執行了jfinal.init完成了對整個框架的初始化!我們的Handler也是在這裡完成初始化的。

boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
    this.servletContext = servletContext;
    this.contextPath = servletContext.getContextPath();

    initPathUtil();

    Config.configJFinal(jfinalConfig);    // start plugin and init logger factory in this method
    constants = Config.getConstants();

    initActionMapping();
    initHandler();
    initRender();
    initOreillyCos();
    initTokenManager();

    return
true; } // 初始化Handler private void initHandler() { Handler actionHandler = new ActionHandler(actionMapping, constants); handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler); }

大家再來看看HandlerFactory,在這裡從ArrayList的尾部向頭部迴圈,完成對每個Handler中的nextHandler引數賦值。下面是Handler的結構,她是一個單向的連結串列。

/**
 * Handler.
 *  * You can config Handler in JFinalConfig.configHandler() method,
 * Handler can do anything under the jfinal action.
 */
public abstract class Handler {

    protected Handler nextHandler;

    /**
     * Handle target
     * @param target url target of this web http request
     * @param request HttpServletRequest of this http request
     * @param response HttpServletRequest of this http request
     * @param isHandled JFinalFilter will invoke doFilter() method if isHandled[0] == false,
     *             it is usually to tell Filter should handle the static resource.
     */
    public abstract void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled);
}

再來、看看HandlerFactory中的getHandler方法。Handler鏈條的末端是ActionHandler,是專門處理action動態請求的地方。

/**
 * Build handler chain
 */
public static Handler getHandler(List handlerList, Handler actionHandler) {
    Handler result = actionHandler;

    for (int i=handlerList.size()-1; i>=0; i--) {
        Handler temp = handlerList.get(i);
        temp.nextHandler = result;
        result = temp;
    }

    return result;
}

最後、我們來看看Handler是怎麼工作的
上圖描述了JFinal中的一個請求的完整過程JFinalFilter->Handler->Action,請求到達Handler中之後有三種結局。

上圖描述了JFinal中的一個請求的完整過程JFinalFilter->Handler->Action,請求到達Handler中之後有三種結局。

① 直接跳出鏈條,執行下一個Filter(如果web.xml中有配置)tomcat、jetty容器對靜態資源請求處理。

如果都不滿足,將返回容器級別的404,可在web.xml中配置404頁。*此處的404不受JFinal配置的404頁控制。

靜態資源進入到ActionHandler時會被直接跳出,執行同上。請求不會到達Action。(示例程式碼:JFinal/ActionHandler.java)

if (target.indexOf('.') != -1) {
    return ;
}

靜態資源進入到ActionHandler時會被直接跳出,執行同上。請求不會到達Action。(示例程式碼:JFinal/ActionHandler.java)

if (target.indexOf('.') != -1) {
    return ;
}

② 請求已經在Handler完成了該有的使命。在Handler執行了render或者在response中返回了我們想要的資料。

該請求也不會到達Action,這裡設定isHandled[0] = true;請求到此為止,也不會去執行後面的Filter。(示例程式碼:jnode/XmlHandler.java)

if (target.endsWith(".xml")) {
    String view = target.replace(".xml", ".vm");
    RenderFactory.me().getRender("/xml".concat(view)).setContext(request, response).render();
    // 跳出
    isHandled[0] = true;
    return;
}

③ 酒肉穿腸過,佛祖心中留。請求會依次經過各個Handler,抵達Action。

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

相關推薦

JFinal Handler原始碼解析——配置工作原理

JFinal頂層是一個Handler鏈是責任鏈模式的一個變種,會攔截到所有請求,包括靜態資源請求。 首先、我們來看看Handler的配置,我們在JFinal的Config中可用來配置自定義的Handler。 @Override public void c

【Spring實戰】Spring註解配置工作原理原始碼解析

一、背景知識在【Spring實戰】Spring容器初始化完成後執行初始化資料方法一文中說要分析其實現原理,於是就從原始碼中尋找答案,看原始碼容易跑偏,因此應當有個主線,或者帶著問題、目標去看,這樣才能最大限度的提升自身程式碼水平。由於上文中大部分都基於註解進行設定的(Spri

React-原始碼分析React Fiber工作原理

為什麼要重寫React React16 以前 React16 以前,對virtural dom的更新和渲染是同步的。就是當一次更新或者一次載入開始以後,diff virtual dom並且渲染的過程是一口氣完成的。如果元件層級比較深,相應的堆疊也

原始碼看hystrix的工作原理

Hystrix是Netflix開源的一個限流熔斷的專案、主要有以下功能: 隔離(執行緒池隔離和訊號量隔離):限制呼叫分散式服務的資源使用,某一個呼叫的服務出現問題不會影響其他服務呼叫。 優雅的降級機制:超時降級、資源不足時(執行緒或訊號量)降級,降級後可以配

深度解析線程工作原理

路徑 cep dead test deadlock end priority interrupt prior   1, 線程的概念     一個程序中的方法有幾條執行路徑, 就有幾個線程   2, 線程的創建     兩種方式:       1, 繼承Thread

Spring原始碼解析 – @Configuration配置類及註解Bean的解析

  在分析Spring 容器建立過程時,我們知道容器預設會載入一些後置處理器PostPRocessor,以AnnotationConfigApplicationContext為例,在建構函式中初始化reader時,載入預設後置處理器。其中 ConfigurationClassPostProcessor這個後置

【原創】Mybaitis生命週期原始碼解析-XML配置啟動--轉載請註明出處

一、準備基本程式碼 注:本文的一切內容都是基於XML配置啟動進行的分析,不適用與Spring-mybatis組合使用場景。 1.建立基本類 package com.zhou; import com.zhou.mapper.BlogMapper; import com.zhou.po

# Mybatis原始碼解析配置載入(二)

Mybatis原始碼解析之配置載入(二) 這一篇是承接上一篇文章Mybatis原始碼解析之配置載入(一),上一篇原本是想把整個配置載入都分析完全,然後發現內容還是比較多,所以決定分成兩篇來說好了,現在就開始剩下的配置分析。 配置載入 繼續回到parseConfigura

Mybatis原始碼解析配置載入(一)

Mybatis原始碼解析之配置載入(一) 用了好幾年的mybatis了,但是很少來鑽研mybatis原理所在,最近抽出空來,就把這一整套原始碼都研究了下,然後發現就是這些東西,mybatis沒啥難度,於是決定把研究的這一整套寫一個mybatis系列,記錄一下,在這些完了以後,順便寫一

Spring原始碼解析配置檔案載入

Spring類的繼承結構圖: Spring運用了大量的模板方法模式和策略模式,所以各位看原始碼的時候,務必留意,每一個繼承的層次都有不同的作用,然後將相同的地方抽取出來,依賴抽象將不同的處理按照不同的策略去處理。 步驟A. 讀取 Resource 檔案形成 Documen

Android 8.1 Handler 原始碼解析

原始碼解析,如需轉載,請註明作者:Yuloran (t.cn/EGU6c76) 一. 前言 基於Android 8.1(API27) 原始碼,分析 Handler 的工作流程。 在 Android 系統中,Zygote 程序是首個 java 程序,同時也是所有 java 程序的父程序。上層應用

Handler原始碼解析

Handler物件通過執行緒的MessageQueue,允許你傳送或者處理一個Message物件或者一個Runnable物件。 每一個Handler物件,都與一個單獨的執行緒和執行緒的MessageQueue相關聯。當你建立一個新的Handler物件, 這

Spring原始碼解析——XmlBeanFactory的建構函式開始看LoadBeanDefinitions

        之前的文章聊過ClassPathResource類,通過這個類,我們從classpath載入到了我們的spring配置檔案,之後,就開始執行XmlBeanFactory的構造過程了:public XmlBeanFactory(Resource resource

Android原始碼分析之訊息機制——Handler原始碼解析

 Android的訊息機制主要是指Handler的執行機制,Handler是Android訊息機制上層介面的實現,它的執行需要Message、MessageQueue和Looper的支撐,下面就來分別介紹它們的實現原理。 1、Message原始碼解析  首先來了解一下Messag

原始碼解析Fragment 返回棧原理

事務提交 流程 原始碼 事務出棧 流程 原始碼 總結 返回棧涉及的類 在看本文前需要熟悉Fragment 的使用,不清楚的可先看:Fragment使用詳解 本文原始碼都是都是v25 的support v4 包下的原始碼。

Eureka原始碼解析配置

    Eureka只要分為2部分,一個server,一個是client(包含生產者和消費者)。    Eureka client: ①從@EnableEurekaClient註解開始看    ②檢視@EnableDiscoveryClient    ③EnableDisco

Binder原始碼解析(客戶端到服務端程式碼流程)

Binder 解析(從客戶端到服務端程式碼流程) 首先從一個例子開始 服務端程式碼: public class WeatherService extends Service{ IWeatherInterface.Stub stub = new

Handler 原始碼解析

Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { }; }; @Override prot

caffe1原始碼解析入門到放棄1):記憶體管理syncedmem.hpp / syncedmem.cpp

/*這些程式碼都是本人在linux-nsight-eclipse環境下純手打。 文章結尾都會丟擲一些本人尚未解決的問題,歡迎各路大神拍磚。 文章屬於學習交流性質,隨著本人學力的提升,此blog將會長期修正更新。 * syncedmem.hpp *

理解SAX解析xml的工作原理

當XMLReader讀到<POEM>標籤時,就會呼叫ContentHandler.startDocument()方法,並把標籤名POEM作為引數傳遞過去。在你實現的startElement()方法中需要做相應的動作,以處理當<POEM>出現時應該做的事情。各個事件隨著解析的過程(也就