源码有毒:Jfinal源码解析(六)

317 查看

继续看Handler.handler方法

public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
        if (target.indexOf('.') != -1) {
            return ;
        }

        isHandled[0] = true;
        String[] urlPara = {null};
        Action action = actionMapping.getAction(target, urlPara);

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

        try {
            Controller controller = action.getControllerClass().newInstance();
            controller.init(request, response, urlPara[0]);

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

            Render render = controller.getRender();
            if (render instanceof ActionRender) {
                String actionUrl = ((ActionRender)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 ;
            }

            if (render == null)
                render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName());
            render.setContext(request, response, action.getViewPath()).render();
        }
    catch (RenderException e) {
        ...异常处理
    }
}

继续往下走,从actionMapping中获取完Action之后,如果没有获取但相应的Action则返回404错误信息,如果Action存在,则从Action中取出初始化时存储到Action中的Controller的Class然后实例化这个Controller

            Controller controller = action.getControllerClass().newInstance();
            controller.init(request, response, urlPara[0]);

紧接着创建了ActionInvocation实例,并调用了invoke()方法

new ActionInvocation(action, controller).invoke();
public void invoke() {
        if (index < inters.length)
            inters[index++].intercept(this);
        else if (index++ == inters.length)  // index++ ensure invoke action only one time
            // try {action.getMethod().invoke(controller, NULL_ARGS);} catch (Exception e) {throw new RuntimeException(e);}
            try {
                action.getMethod().invoke(controller, NULL_ARGS);
            }
            catch (InvocationTargetException e) {
                Throwable cause = e.getTargetException();
                if (cause instanceof RuntimeException)
                    throw (RuntimeException)cause;
                throw new RuntimeException(e);
            }
            catch (RuntimeException e) {
                throw e;
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
    }

在invoke()方法中,显示依次调用了当前action请求对于的拦截器,在所有的拦截器执行完之后,则是调用了具体Action请求对应的Controller中的具体方法

Render render = controller.getRender();
            if (render instanceof ActionRender) {
                String actionUrl = ((ActionRender)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 ;
            }

如果当前的Action请求是一个重定向请求,则再递归调用handle方法
调用了Render.render()方法,这里看一个简单的例子JsonRender中的render()方法

    public void render() {
        if (jsonText == null)
            buildJsonText();

        PrintWriter writer = null;
        try {
            response.setHeader("Pragma", "no-cache");   // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            response.setContentType(forIE ? contentTypeForIE : contentType);
            writer = response.getWriter();
            writer.write(jsonText);
            writer.flush();
        } catch (IOException e) {
            throw new RenderException(e);
        }
        finally {
            if (writer != null)
                writer.close();
        }
    }

这里代码就比较情切了,把jsonText返回前台调用者,而JsonText在则是把创建JsonRender()对象是传入的数据对象直接转换成了Json字符串

public JsonRender(Object object) {
        if (object == null)
            throw new IllegalArgumentException("The parameter object can not be null.");
        this.jsonText = JsonKit.toJson(object, convertDepth);
    }