本文摘自或翻译自JSR 252,JavaServer Faces Specification 1.2 Final Release,如有转载,请声明出处!
1. JSF请求处理流程

2. 获取Faces相关对象
javax.faces.lifecycle.LifeCycle
LifecycleFactory lFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
javax.faces.context.FacesContext
FacesContextFactory fcFactory = (FacesContextFactory)
FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
FacesContext facesContext =
fcFactory.getFacesContext(context, request, response,lifecycle);
javax.faces.component.UIViewRoot
视图是以UIViewRoot作为根的一个树状结构,并且使用一个标识符标记。
String viewId = ...identifier of the desired Tree...;
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot view = viewHandler.createView(facesContext, viewId);
javax.faces.render.RenderKit
可以通过转换不同的RenderKit来对同种类型的组件进行不同的显示。
String renderKitId = ... identifier of desired RenderKit ...;
RenderKitFactory rkFactory = (RenderKitFactory)
FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit = rkFactory.getRenderKit(renderKitId,facesContext);
view.setRenderKitId(renderKitId);
3. 值的处理
基本上,JSF就是一种从客户端用户获取数据,然后将数据传输到模型层进行处理的方式。下面假设在JSP/HTTP的情况下,值的处理流程:
应用请求的值phase:用户点击按钮,提交了表单,表单的值以name=value的方式,作为HTTP请求POST数据,既然怒JSF请求处理周期,最终进入应用请求的值阶段,在该阶段,视图中每个UIComponent的每个Renderer的decode方法被调用,Renderer从请求中获取数据,并传递给组件的setSubmittedValue方法,数据的类型是EditableValueHolder的实例。如果组件的immediate属性是true,那么在解码后直接运行验证。
处理验证器phase:对视图的根调用processValidators方法。对于视图中的每个EditableValueHolder,如果没有设置immediate方法,那么对视图中的每个UIInput执行验证,否则,已经执行了验证,这个阶段不做任何操作。
执行验证:调用UIInput的validate()方法。详细内容请参考javadocs。该方法从组件中获取数据,然后获取组件的Renderer,然后调用Renderer的getConvertedValue()方法,将提交的值传递。如果转换过程或者验证过程出错的话,就会激活对应的事件,进行处理。
更新模型的值阶段:对于每个UIInput组件,调用它的updateModel()方法。
4. L10N和I18N(本地化和国际化)
JSF是国际化的。JSF的国际化是基于Servlet、JSP和JSTL规范的。国际化在请求处理周期的很多阶段发生。下面根据功能进行任务的区分:
定义活跃Locale:JSF包含活跃Locale的概念,用来查找所有的本地化资源,转换器必须使用这个Locale来进行转换。这个Locale是作为当前FacesContext的UIViewRoot的locale属性而存在的。可以在faces-config中进行配置:
<faces-config>
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>de</supported-locale>
<supported-locale>fr</supported-locale>
<supported-locale>es</supported-locale>
</locale-config>
</application>
默认的locale是en,同时支持de、fr、es这样的locale。这些元素可以使Application实例获取特定Locale的数据。
UIViewRoot的locale属性在ViewHandler.createView()方法中决定。
应用程序可以直接调用UIViewRoot.setLocale()方法,但是也可以在页面的<f :view>中设置locale属性。格式为[{-|_}country[{-|_}cariant]],没有冒号,例如"ja_JP_SJIS"。个部分之间的符号是"_"或者"-"。
无论JSP在哪里被使用,活跃Locale总是作为request scope下被设置到JSTL类javax.servlet.jsp.jstl.core.Config中,key为Config.FMT_LOCALE。
字符编码:请求和响应的字符编码按照如下份那个是设置和解释。
初次请求Faces应用程序时,不修改请求的编码方式,依赖底层请求对象来正确的解析请求参数。在render-response阶段开始,ViewHandler必须确保响应的Locale已经设置成UIViewRoot的locale属性值,例如调用ServletResponse.setLocale()方法。在render-response结束的时候,ViewHandler必须保存session中(当且仅当session存在的时候)底层response对象使用的响应的字符编码。
当有后续的请求时,在任何访问请求参数的方法在调用之前,ViewHandler必须检查Content-Type头,获取charset属性,并使用它的值作为请求的编码方式。当Content-Type头不包含charset属性时,将使用之前保存在session中的编码方式,如果没有发现编码方式,那么同样适用请求原有的编码方式。
本地化文本:API中并没有对本地化文本的直接支持,但是JSP层提供了方便的标签来将ResourceBundle转换为java.util.Map对象,并在指定范围内来获取。大多数JSF组件支持从模型层获取显示的数据,所以在模型层来进行本地化是比较容易的。JSF提供了<f :loadBundle>标记,将REsourceBundle的内容加载到Map中,从而使得它的消息可以在model层获取,例如:
<f:loadBundle basename=”com.foo.industryMessages.chemical" var=”messages” />
<h:outputText value=”#{messages.benzene}” />
上面的语句会使名为com.foo.industryMessages.chemical加载到Map中,并保存在请求范围,key为messages。
本地化应用程序信息:当在转换、验证和其他应用程序动作发生错误时,JSF可以处理本地化错误和消息。javax.faces.application.FacesMessage用来对消息进行封装。JSF实现必须提供javax.faces.Messages ResourceBundle,包含必要的key和标准的消息,需要的key如下:
■ javax.faces.component.UIInput.CONVERSION -- {0}: Conversion error occurred
■ javax.faces.component.UIInput.REQUIRED -- {0}: Validation Error: Value is required
......
JSF应用程序可能提供自己的消息,或者覆盖标准的消息,这些可以在应用程序配置文件中使用<messsage-bundle>元素来实现。既然Java平台的ResourceBundle中没有概括和详细的概念,JSF集成了ResourceBundle中key作为消息的概括的策略。详细内容存储在同样的key下,作为概括。并追加_detail。
消息可以通过使用<h:message>和<h:messages>来显示。
5. 组件
组件标识符
组件都具有组件标识符,组件标识符在共享的名称容器(naming container)必须是唯一的。组件标识符的组成规则如下:
必须以字符开头
后续字符可以是字符(letter),数字(digit),-(dash)或者_(underscore)
为了使JSF响应最小化,建议使用简短的标识符。
可以通过getId()和setId(String)来获取和设置组件的标识符。
组件类型
虽然不是UIComponent的属性,但是component-type是对每个UIComponent子类很重要的数据。它可以运行Application的实例创建一个指定类型的UIComponent的子类对象。
组件家族
组件都是有家族的。
值表达式属性
可以使用值表达式来避免使用硬编码。
......
树状结构
可以通过使用getParent方法获取父组件,对于不是UIComponent或者根节点组件,该方法返回null;可以通过getChildren方法返回子组件的List。也可以通过调用getFacets方法返回Map接口。同时,可以通过getChildCount方法获取子节点的个数。
6. 标准组件

发表于 @ 2008年06月10日 22:16:00|编辑|收藏