HandlerFactory
HandlerFactory是不可实例化的,因为 它的构造 函数 特意定位 私有 的;它有一个 静态的方法叫做 getHandler,它有两个参数 ,一个是Handler的List类型,另一个是一个单一的handler,代码如下 :
public static Handler getHandler(List<Handler> handlerList, Handler actionHandler) { Handler result = actionHandler; for (int i=handlerList.size()-1; i>=0; i--) { Handler temp = handlerList.get(i); temp.next = result; temp.nextHandler = result; result = temp; } return result; }
如上代码所示 ,从 最后一个 开始 循环 ,然后 把它的next都 赋值 为 第二个参数 的Handler,然后最后 返回 的Handler为第一个参数List中 第一个元素,并 带上了next参数 。使用它的地方就是JFinal的initHandler方法。
private void initHandler() { Handler actionHandler = new ActionHandler(actionMapping, constants); handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler); }
不过 我有一点疑问,这个 getHandlerList()方法,能带给 我真正的List吗 ?因为我看 没有 地方 去add它,也就是说,这 个List永远只是 一个 size为 0的List,不知道@JFinal 怎么看这个问题,求解。
Handler
我们 先来 看看 代码 ,这是 一个 抽象类,其中 nextHandler 被 标记为过时的,也就是说 已经 没多少地方用到 了。
public abstract class Handler { /** * The next handler */ protected Handler next; /** * Use next instead of nextHandler */ @Deprecated 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); }
关键 是看 上面的handle方法,这是一个 抽象方法。这里面 包含了ServletRequest和Response,以及 一个 boolean数组 ,标识是否 被处理 过,我觉得 熟悉代码 还是 要 从 它的实现来分层 发散,所以 下面 的都是 它的实现类。
ActionHandler
这个类继承了上面 说的Handler类,首先我们 上 几个属性 ,下面几个 属性我们 需要 关心哪些东西 呢?首先 是ActionMapping和RenderManager,其中ActionMapping是通过 构造函数 注入进来的。而RenderManager.me其实 只是一个RenderManager的一个实例而已,
private final boolean devMode; private final ActionMapping actionMapping; private static final RenderManager renderManager = RenderManager.me(); private static final Log log = Log.getLog(ActionHandler.class); public ActionHandler(ActionMapping actionMapping, Constants constants) { this.actionMapping = actionMapping; this.devMode = constants.getDevMode(); }
说到RenderManager.me(),不得 不佩服 JFinal里面的一个 经常看到的东西 ,下面 贴代码 ,下面的代码 在 JFinal里面经常被 复用,他的作用 其实就是创建一个 实例 的单利 ,而且这个实例是 随着 Tomcat进程启动的。
private static final RenderManager me = new RenderManager(); private RenderManager() {} public static RenderManager me() { return me; }
下面 我们 来 看看 其中 的核心 方法handle,在了解 这个之前,我 觉得 还是有 必要看看有 哪些地方引用 到了这个ActionHandler,经过查找 ,发现还是这个地方:
Handler actionHandler = new ActionHandler(actionMapping, constants);
那么 我们的集中点就是 这个actionMapping了,我们 必须知道这里面 的实体 的结构 ,经过发现,在JFinal.java当中的me()方法中有一个方法 可以初始化。
private void initActionMapping() { actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors()); actionMapping.buildActionMapping(); Config.getRoutes().clear(); }
从上面的代码 当中,我们 可以 知道 几个地方 ,ActionMapping肯定是和route和intercertor(拦截器 )相关联的,我们 进入 ActionMapping的构造函数一探究竟,发现作者已经注释掉 了 第二个 参数 。
ActionMapping(Routes routes, Interceptors interceptors) { this.routes = routes; // this.interceptors = interceptors; }
我们再来看看 handle方法:
if (target.indexOf(‘.‘) != -1) { return ; } isHandled[0] = true; String[] urlPara = {null}; Action action = actionMapping.getAction(target, urlPara);
首先如果 target包含.的 话 直接 结束,如果通过,把第一个isHandleed的布尔参数设置为 true.下面 我们 来 看看 getAction方法,
Action getAction(String url, String[] urlPara) { Action action = mapping.get(url); if (action != null) { return action; } // -------- int i = url.lastIndexOf(‘/‘); if (i != -1) { action = mapping.get(url.substring(0, i)); urlPara[0] = url.substring(i + 1); } return action; }
我们 再来 看看 mapping这个属性,其实 从 上面 下面 的代码我们可以 看书,target-url中可以获取 这个target的action.
private final Map<String, Action> mapping = new HashMap<String, Action>();
今天 就 写到这里,未完待续。。。