JSF教程(6)——生命周期中处理请求

来源:互联网 发布:java swing 日期控件 编辑:程序博客网 时间:2024/06/06 09:30

JSF处理一个initial请求的时候程序将会创建一个新的view并且将它储存在FacesContext的实例中,这里需要注意的是只有在JSFResponse指向另一个JSFView的时候上面的过程才会执行。其实这很好理解,如果简单一个超链接或者一个按钮将请求发送到服务器,而这个请求仅仅是跳转到一个不包含任何JSF组件的页面那么在服务端将没有任何View被产生,更别说被储存在FacesContext的实例中了。

关于FacesContext实例,在其中包含了处理request的和创建response的所有需要的信息。一般国内的翻译都会将“Context”翻译为“上下文”但是笔者更愿意将其理解为“一个保存了需要信息的环境”。在FacesContext实例中可以找到此次已经创建并存储的View以及和此次request以及Response有关的所有的信息。然后程序将调用用来渲染这个view的所有的资源,最后调用renderResponse方法立即渲染这个view(上篇博客图中的标有Render Response的箭头)。

可能有些情况下JSF需要重定向到其他的系统资源比如web service或者产生一个不包含任何JSF组件的response,在这种情况下开发人员必须调用responseComplete方法跳过Render Response这个步骤(步骤图中标有Response Complete步骤的箭头),道理很简单上面的两种情况都是不需要JSF去渲染页面的,所以响应就直接结束了。

读者可以参考JSF源码(jsf-impl-2.1.3,ViewHandlerImpl.java代码片段)

......public UIViewRoot restoreView(FacesContext context, String viewId) {        if (context == null) {            String message = MessageUtils.getExceptionMessageString                (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context");            throw new NullPointerException(message);        }        ExternalContext extContext = context.getExternalContext();        String mapping = Util.getFacesMapping(context);        UIViewRoot viewRoot = null;        if (mapping != null) {            if (!Util.isPrefixMapped(mapping)) {                viewId = convertViewId(context, viewId);            } else {                viewId = normalizeRequestURI(viewId, mapping);            }        }        // maping could be null if a non-faces request triggered        // this response.        if (extContext.getRequestPathInfo() == null && mapping != null &&            Util.isPrefixMapped(mapping)) {            // this was probably an initial request            // send them off to the root of the web application            try {                context.responseComplete();                if (logger.isLoggable(Level.FINE)) {                    logger.log(Level.FINE, "Response Complete for" + viewId);                }                extContext.redirect(extContext.getRequestContextPath());            } catch (IOException ioe) {                throw new FacesException(ioe);            }        } else {            // this is necessary to allow decorated impls.            ViewHandler outerViewHandler =                    context.getApplication().getViewHandler();            String renderKitId =                    outerViewHandler.calculateRenderKitId(context);            viewRoot = Util.getStateManager(context).restoreView(context,                                                                 viewId,                                                                 renderKitId);        }        return viewRoot;    }......


上面的情况都不是我们平时常用的,仅仅是极少数的情况。在平时的开发过程当中我们遇到最常见的情况是从JSF页面跳转到另外的JSF页面。这时候就要经历图中主要的步骤(向下的箭头),转换,校验,模型更新,产生response。这与我们之前所了解的所有Web应用的处理步骤基本上是一致的。在这里需要读者注意的是在组件中有一个immediate属性,如果该组件的词属性设置为true那么JSF的生命周期将不按照正常情况进行下去。对于组件的immediate属性我们可以理解为:是否要求JSF对该组件立即(immediate)进行数据的校验(Validation)、更新值等操作,而不是在后面的步骤中进行操作,注意很多开发者认为immediate设置为true就是不进行数据的校验以及后面的一些列操作,这样理解是欠妥的。

接下来的博客将详细阐述JSF生命周期中的各个阶段的作用以及相关源码的分析。

2 0
原创粉丝点击