ActionHandler.java

  这个类继承了上面 说的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>();

 以上的东西的链接示例如下所示 ,可以 结合 上面的代码 ,从 url中 获得 最后一个斜杠后的参数。也就是 para.

    /**
* Support four types of url
* 1: http://abc.com/controllerKey ---> 00
* 2: http://abc.com/controllerKey/para ---> 01
* 3: http://abc.com/controllerKey/method ---> 10
* 4: http://abc.com/controllerKey/method/para ---> 11
* The controllerKey can also contains "/"
* Example: http://abc.com/uvw/xyz/method/para
*/

  然后我们 回到handle方法吧 ,继续看下面的代码,如果 Action为 NULL,那么就返回 404错误 。

        if (action == null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
}
renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render();
return ;
}

  然后我们 看下面的代码 ,从 下面 的代码我们 得知,controller其实 是由action生成 的,因为我们之前 未分析 过 Controller,我们 现在 只要 理解这是一个 Controller的 Class类就行 了,然后生成 一个 新的实例,就OK了。

Controller controller = action.getControllerClass().newInstance();

  然后 我们 再看 下面 的代码 ,其实这只是 对 当前controller实例进行构造注入。

controller.init(request, response, urlPara[0]);

  然后 我们 继续 看 后面的代码,这里 提到 了一个概念,就是devMode,从字面上来说,这是开发模式 ,我们 暂且 不管 它,先 解决 通用模式下的问题。

            if (devMode) {
if (ActionReporter.isReportAfterInvocation(request)) {
new Invocation(action, controller).invoke();
ActionReporter.report(target, controller, action);
} else {
ActionReporter.report(target, controller, action);
new Invocation(action, controller).invoke();
}
}
else {
new Invocation(action, controller).invoke();
}

  我们先来 看看 这句话,这句话 其实 就是 把当前action和controller注入 到一个新的Invocation中,其中有 一个 invoke方法,因为 这牵扯 到过多的知识,连 我可能都 不太 懂 ,所以 暂且放到 一边去,不做讨论。

new Invocation(action, controller).invoke();

  然后 我们 再看 下面一句 代码,这说明可以从 controller里面 得到render整个对象 。

Render render = controller.getRender();

  然后 我们看 下面的 代码 ,如果render是ForrwardActionRender。

            if (render instanceof ForwardActionRender) {
String actionUrl = ((ForwardActionRender)render).getActionUrl();
if (target.equals(actionUrl)) {
throw new RuntimeException("The forward action url is the same as before.");
} else {
handle(actionUrl, request, response, isHandled);
}
return ;
}

  我们 首先 需要了解一下ForwardRender是一个 什么 东西 ,然后 我们发现,其实 这 就是 一个 继承 了Render类的一个子类,里面就 多了一个actionUrl而已。

    private String actionUrl;

    public ForwardActionRender(String actionUrl) {
this.actionUrl = actionUrl.trim();
} public String getActionUrl() {
return actionUrl;
}

  然后我们来看看 下面 的代码,其实就是 自己啊,这里实现了一个递归 ,自己调用 自己,为什么呢,不得而知。

handle(actionUrl, request, response, isHandled);

  那么如果render为空,会执行如下 操作,设置一个 默认的Render,渲染器。

    if (render == null) {
render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName());
}

  最后会有 这么一句话 ,其实就是 设置request和response以及viewpath.

render.setContext(request, response, action.getViewPath()).render();

  今天就 写到这里 ,重要的是查漏补缺。

JFinal源码 分析之 Core包分析的更多相关文章

  1. JFinal 源码分析 [DB+ActiveRecord]

    我记得以前有人跟我说,“面试的时候要看spring的源码,要看ioc.aop的源码"那为什么要看这些开源框架的源码呢,其实很多人都是"应急式"的去读,就像读一篇文章一下, ...

  2. 老李推荐:第5章3节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动脚本

    老李推荐:第5章3节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动脚本   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性 ...

  3. 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用

    老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用   上一节我们描述了monkey的命令处理入口函数run是如何调用optionP ...

  4. 老李推荐:第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览

    老李推荐:第5章2节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动流程概览   每个应用都会有一个入口方法来供操作系统调用执行,Monkey这个应用的入口方法就 ...

  5. 老李推荐:第5章1节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 官方简介

    老李推荐:第5章1节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 官方简介   在MonkeyRunner的框架中,Monkey是作为一个服务来接受来自Monkey ...

  6. 老李推荐:第6章8节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-小结

    老李推荐:第6章8节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-小结   本章我们重点围绕处理网络过来的命令的MonkeySourceNetwork这个事 ...

  7. 老李推荐:第6章7节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-注入按键事件实例

    老李推荐:第6章7节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-注入按键事件实例   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜 ...

  8. 老李推荐:第6章6节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令队列

    老李推荐:第6章6节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令队列   事件源在获得字串命令并把它翻译成对应的MonkeyEvent事件后,会把这些 ...

  9. 老李推荐:第6章4节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-翻译命令字串

    老李推荐:第6章4节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-翻译命令字串   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自 ...

随机推荐

  1. motan负载均衡/zookeeper集群/zookeeper负载均衡的关系

    motan/dubbo支持负载均衡.zookeeper有集群的概念.zookeeper似乎也能做负载均衡,这3者是什么关系呢? 3个概念:motan/dubbo负载均衡.zookeeper集群.zoo ...

  2. 1c19b35b005744d55261682b361804fa 这个是MD5

    1c19b35b005744d55261682b361804fa   这个是MD51c19b35b005744d55261682b361804fa   这个是MD51c19b35b005744d552 ...

  3. SPATRA的使用

    SPATRA是kali里的集成工具,可以自动化渗透测试 在命令行里键入:sparta即可进入 进去后单机左边空白处 输入你要进行渗透测试的IP 正在扫描中 点击bute可以进入hydra

  4. MATLAB学习笔记

    魔方矩阵(magic(阶数)) 魔方矩阵又称幻方,是有相同的行数和列数,并在每行每列.对角线上的和都相等的矩阵.魔方矩阵中的每个元素不能相同.你能构造任何大小(除了2x2)的魔方矩阵. 希尔伯特矩阵( ...

  5. 51 nod 1211 数独 DLX

    原题链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1211 调了挺久的,自己的一份舞蹈链模板…… 算是在网上见到的模 ...

  6. HDU--2017

    字符串统计 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  7. easyUI返回类型total,rows

  8. 你必须知道的session与cookie

    Session本质 提到Session我们能联想到的就是用户登录功能,而本身我们使用Session的基础是通过url进行访问的,也就是使用http协议进行访问的,而http协议本身是无状态的,那么问题 ...

  9. eclipse配置虚拟路径后,每次启动tomcat都会虚拟路径失效的问题解决

    由于,eclipse启动tomcat部署项目并不是直接把项目放到tomcat的webapps目录下的,而是从我们在eclipse配置的外部tomcat中取出二进制文件,在eclipse内部插件中作为t ...

  10. 关于vueThink框架打包发布的一些问题

    刚开始发布自己的vueThink项目的时候,总是出现404错误,后来经过上网查找,发现是路径的问题,这方面的知识,网上很多,就不过多阐述了.我主要想说的是自己的项目发布的时候,admin账号登录的时候 ...