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

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生命周期中的各个阶段的作用以及相关源码的分析。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值