zoukankan      html  css  js  c++  java
  • JFinal源码 分析之 Core包分析

    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();

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

  • 相关阅读:
    SpringCloud Ribbon实现负载均衡,SpringCloud Ribbon自定义策略
    springCloud zookeeper整合,Java Zookeeper微服务注册中心整合
    SpringCloud Eureka安装和使用,SpringCloud使用Eureka作为服务注册中心
    Linux yum安装Consul服务中心,Centos7在线安装consul
    SpringCloud consul安装和使用,Windows Consul安装和使用,Java consul服务中心安装和使用
    哔哩哔哩视频下载到电脑,bilibili UWP下载的视频重命名,blibli视频下载到电脑
    elasticsearch kibana安装和配置
    elasticsearch安装和配置,elasticsearch启动报错:can not run elasticsearch as root
    cmd打开当前文件所在目录,cmd进入当前文件目录,cmd进入指定目录
    京东到家 首页 笔记
  • 原文地址:https://www.cnblogs.com/kmsfan/p/7497396.html
Copyright © 2011-2022 走看看