JSF规范(四)

9 篇文章 0 订阅

本文是基于JSF规范的翻译而来,并省掉一些无关紧要的章节。如有不当之处请大家指正。

作者:youfly      email:seedcloned-pub@yahoo.com.cn

转载请注明出处:www.jfuns.com www.jfuns.cn http://blog.csdn.net/youfly



2.5 Concepts that impact several lifecycle phases

本章试图通过给读者提供一个影响“请求处理生命周期”各个阶段的一些复杂概念的 “big picture”视图。

2.5.1 Value Handling

在基本原理层面,JavaServer Faces提供了一个从用户那里获取数据并提供给模型层处理的一个途径。关于从用户到模型的值处理流在这份规范的其他地方描述,但是可以从这里得到一个整体的认识。下面的描述假定是JSP/HTTP的情形,并且所有的组件都拥有Renderers

 

2.5.1.1 Apply Request Values Phase

当用户点击按钮并且引发提交,将发送name=value对形式的HTTP请求POST数据到服务器中。这就进入了JSF的“请求处理生命周期”,并且最终我们进入了Apply Request Values阶段。在这个阶段视图中的每个组件的每个Renderer上的decode()方法被调用。Renderer从请求中取出值,并将这些值传递给组件的setSubmittedValue()方法,当然,这些组件应该是EditableValueHolder的实例。如果组件的”immediate”属性被设置成true,我们在decoding后将立即执行验证。请阅读下面的内容以得到执行验证时所发生的事情。

 

2.5.1.2 Process Validators Phase

视图根的processValidators()方法被调用。对于视图中的每一个EditableValueHolder,要是”immediate”属性没有设置,我们将执行视图中的每一个UIInput的验证。否则,则表示验证已经被执行,这个阶段不需要作任何处理。

 

2.5.1.3 Executing Validation

请阅读javadoc文件当到UIInput.validate()方法更为详细的信息,但基本上,这个方法从组件中获取提交的值(Apply Request Values期间被设置) ,取得组件的Renderer并调用它的getConvertedValue()方法,并传递到取的值给这个方法。如果发生数据转换错误,则按照这个getConvertedValue方法的javadoc文档描述进行处理。否则,所有和这个组件绑定的validators被请求来验证转换的值是否合法。如果发生验证错误,则按照Validator.validate()方法的javadoc描述进行处理。转换值通过组件的setValue()设置到组件中,如果值被改变,则触发ValueChangeEvent事件。

2.5.1.4 Update Model Values Phase

视图中的每一个UIInput组件,它们的updateModel方法被调用。这个方法只是在验证期间组件的本地值(Local value)被设置并且页面的作者配置了设置这个组件值到模型(Model)层的时候才有效。这个阶段只是简单的根据页面作者的配置将UIInput组件转换成功的本地值设置到模型(Model)中。在试图将值设置到模型(Model)层时所发生的任何错误都按照UIInput.updateModel()方法的javadoc文档描述来处理。

 

2.5.2 Localization and Internationalization (L10N/I18N)

JavaServer Faces被完全的国际化,JavaServer Faces提供的I18N能力是基于Servlet,JSPJSTL规范提供的I18N概念。

I18N happens at several points in the request processing lifecycle, but it is easiest to explain what goes on by

breaking the task down by function.

2.5.2.1 Determining the active Locale

JSF用活动Locale的概念来查找所有的本地化资源。转换器必须使用这个Locale来执行他们的转换。Locale保存在当FacesContextUIViewRootlocale JavaBeans属性中。应用开发者可以通过配置文件WEB-INF/faces-config.xml 来告诉JSF当前应用所支持的locales。例如:

<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>

这个应用的默认localeen,但是它支持de,freslocales。这些元素将引起Application实例封装Locacle数据。请阅读javadocs文档以得到更为详细的信息。

ViewHandler执行createView()方法期间,决定并设置UIViewRoot对象的locale。这个方法必须根据应用所支持的Locale及用户参数来决定当前的活动Locale。请阅读javadocs文档以得到更为详细的信息。应用能够直接的调用UIViewRoot.SetLocale()方法,但页面的作者也可以通过<f:view>标记来覆盖UIViewRootlocale属性。这个属性值必须以language[{-

|_}country[{-|_}variant]]的形式指定,且不能包含冒号,例如”ja_JP_SJIS”。片段之间的分隔符可以是'-' 或者 '_'

 

在所有使用JSP的情况下,活动locale通过Config.FMT_LOCALE这个key被设置进“request scope”JSTLjavax.servlet.jsp.jstl.core.Config类中。

 

2.5.2.2 Determining the Character Encoding

请求和响应的字符集编码通下面列的方法被设置和说明。

 

一个初始的JSF web应用请求,它的字符集编码是否保持未更改状态,依赖于request对象正确的解析request参数。

 

render-response阶段的开始,ViewHandler必须确保response Locale设置到UIViewRoot中,例如在servlet环境中调用ServletResponse.setLocale()方法。设置responseLocale将影响response的字符集编码,请阅读ServletPorlet规范得到更为详细的信息。

render-response阶段的结束,ViewHandler必须使用众所周知的实现依赖的keyresponse(例如servlet或者portlet Response)的字符集编码保存在session(仅仅在session存在时)中。

 

在后续的postback处理中,任何调用访问request parametersExternalContext方法被调用前,ViewHandler必须检查Content-Type头,取得charset属性,并用取到的值设置request对象的字符集编码。如果Content-Type头没有包含charset属性,则用先前保存在session(仅仅在session存在时)中的字符集编码设置request对象的编码。如果没有任何字符集编码找到,则应该保持请求的字符集编码不变。

 

上面的算法提供了一个让有特殊需求应用可以调整requestresponse字符的机制。如例JSP页面可通过page指示符设置页面的contentType属性使用固定的字符集编码,请阅读servlet,portletjsp规范得到更为详细的信息。

注意,Servlet 2.4JSP 2.0之前的字符集编码规则并不精确,因此我们要特别注意不同容器之间的移植。

 

2.5.2.3 Localized Text

没有直接支持本地化文本的API,但JSP层提供了一个便利的标记来将Resource Bundle转换成java.util.Map,并保存它到命名空间中,因此我们可以得到它。这一节描述如果将本地化的文本显示给最终用户。这些包括图片,标签,按钮文本,提示等。自从所有的JSF组件允许从模型层得到它们的显示信息,因此就容易的通过模块层进行本地化。为了方便,JSF提供了一个<f:loadBundle>标记,这个标记能够将ResourceBundle载入到Map中,并将它request scope的命名空间中,因此在模型层就可以用相同的机制来访问这些数据。例如:

<f:loadBundle basename=”com.foo.industryMessages.chemical” var=”messages” />

<h:outputText value=”#{messages.benzene}” />

这将引起名称为com.foo.industryMessages.chemical ResourceBundle载入到Map中,并保存到keymessages request属性中。本地化内容能够通过一般的值表达式语法取出。

2.5.2.4 Localized Application Messages

这节描述了JSF如如何处理在转换,验证,或其他application action时发送的错误及提示信息。JSFjavax.faces.application.FacesMessage提供了封装的消息摘要,详细及级别信息。JSF实现必须提供包含所有标准消息的javax.faces.Messages ResourceBundle。下面列出所有的标准消息(和非标准的预留消息文本)key

javax.faces.component.UIInput.CONVERSION -- {0}: Conversion error occurred

javax.faces.component.UIInput.REQUIRED -- {0}: Validation Error: Value is required

javax.faces.component.UIInput.UPDATE -- {0}: An error occurred when processing your

submitted information

javax.faces.component.UISelectOne.INVALID -- {0}: Validation Error: Value is not valid

javax.faces.component.UISelectMany.INVALID -- {0}: Validation Error: Value is not

valid

javax.faces.converter.BigDecimalConverter.DECIMAL={2}: ''{0}'' must be a signed

decimal number.

javax.faces.converter.BigDecimalConverter.DECIMAL_detail={2}: ''{0}'' must be a

signed decimal number consisting of zero or more digits, that may be followed by a

decimal point and fraction. Example: {1}

javax.faces.converter.BigIntegerConverter.BIGINTEGER={2}: ''{0}'' must be a number

consisting of one or more digits.

javax.faces.converter.BigIntegerConverter.BIGINTEGER_detail={2}: ''{0}'' must be a

number consisting of one or more digits. Example: {1}

javax.faces.converter.BooleanConverter.BOOLEAN={1}: ''{0}'' must be 'true' or 'false'.

javax.faces.converter.BooleanConverter.BOOLEAN_detail={1}: ''{0}'' must be 'true' or

'false'. Any value other than 'true' will evaluate to 'false'.

javax.faces.converter.ByteConverter.BYTE={2}: ''{0}'' must be a number between 0 and

255.

javax.faces.converter.ByteConverter.BYTE_detail={2}: ''{0}'' must be a number between

0 and 255. Example: {1}

javax.faces.converter.CharacterConverter.CHARACTER={1}: ''{0}'' must be a valid

character.

javax.faces.converter.CharacterConverter.CHARACTER_detail={1}: ''{0}'' must be a

valid ASCII character.

javax.faces.converter.DateTimeConverter.DATE={2}: ''{0}'' could not be understood as a

date.

javax.faces.converter.DateTimeConverter.DATE_detail={2}: ''{0}'' could not be

understood as a date. Example: {1}

Chapter 2 Request Processing Lifecycle 2-19

javax.faces.converter.DateTimeConverter.TIME={2}: ''{0}'' could not be understood as a

time.

javax.faces.converter.DateTimeConverter.TIME_detail={2}: ''{0}'' could not be

understood as a time. Example: {1}

javax.faces.converter.DateTimeConverter.DATETIME={2}: ''{0}'' could not be

understood as a date and time.

javax.faces.converter.DateTimeConverter.DATETIME_detail={2}: ''{0}'' could not be

understood as a date and time. Example: {1}

javax.faces.converter.DateTimeConverter.PATTERN_TYPE={1}: A 'pattern' or 'type'

attribute must be specified to convert the value ''{0}''.

javax.faces.converter.DoubleConverter.DOUBLE={2}: ''{0}'' must be a number consisting

of one or more digits.

javax.faces.converter.DoubleConverter.DOUBLE_detail={2}: ''{0}'' must be a number

between 4.9E-324 and 1.7976931348623157E308 Example: {1}

javax.faces.converter.EnumConverter.ENUM={2}: ''{0}'' must be convertible to an enum.

javax.faces.converter.EnumConverter.ENUM_detail={2}: ''{0}'' must be convertible to an

enum from the enum that contains the constant ''{1}''.

javax.faces.converter.EnumConverter.ENUM_NO_CLASS={1}: ''{0}'' must be

convertible to an enum from the enum, but no enum class provided.

javax.faces.converter.EnumConverter.ENUM_NO_CLASS_detail={1}: ''{0}'' must be

convertible to an enum from the enum, but no enum class provided.

javax.faces.converter.FloatConverter.FLOAT={2}: ''{0}'' must be a number consisting of

one or more digits.

javax.faces.converter.FloatConverter.FLOAT_detail={2}: ''{0}'' must be a number

between 1.4E-45 and 3.4028235E38 Example: {1}

javax.faces.converter.IntegerConverter.INTEGER={2}: ''{0}'' must be a number

consisting of one or more digits.

javax.faces.converter.IntegerConverter.INTEGER_detail={2}: ''{0}'' must be a number

between -2147483648 and 2147483647 Example: {1}

javax.faces.converter.LongConverter.LONG={2}: ''{0}'' must be a number consisting of

one or more digits.

javax.faces.converter.LongConverter.LONG_detail={2}: ''{0}'' must be a number between

-9223372036854775808 to 9223372036854775807 Example: {1}

javax.faces.converter.NumberConverter.CURRENCY={2}: ''{0}'' could not be understood

as a currency value.

javax.faces.converter.NumberConverter.CURRENCY_detail={2}: ''{0}'' could not be

understood as a currency value. Example: {1}

javax.faces.converter.NumberConverter.PERCENT={2}: ''{0}'' could not be understood as

a percentage.

2-20 JavaServer Faces Specification • May 2006

javax.faces.converter.NumberConverter.PERCENT_detail={2}: ''{0}'' could not be

understood as a percentage. Example: {1}

javax.faces.converter.NumberConverter.NUMBER={2}: ''{0}'' is not a number.

javax.faces.converter.NumberConverter.NUMBER_detail={2}: ''{0}'' is not a number.

Example: {1}

javax.faces.converter.NumberConverter.PATTERN={2}: ''{0}'' is not a number pattern.

javax.faces.converter.NumberConverter.PATTERN_detail={2}: ''{0}'' is not a number

pattern. Example: {1}

javax.faces.converter.ShortConverter.SHORT={2}: ''{0}'' must be a number consisting of

one or more digits.

javax.faces.converter.ShortConverter.SHORT_detail={2}: ''{0}'' must be a number

between -32768 and 32767 Example: {1}

javax.faces.converter.STRING={1}: Could not convert ''{0}'' to a string.

javax.faces.validator.DoubleRangeValidator.MAXIMUM -- {1}: Validation Error: Value is

greater than allowable maximum of ‘’{0}’’

javax.faces.validator.DoubleRangeValidator.MINIMUM -- {1}: Validation Error: Value is

less than allowable minimum of ‘’{0}’’

javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE -- {2}: Validation Error:

Specified attribute is not between the expected values of {0} and {1}.

javax.faces.validator.DoubleRangeValidator.TYPE -- {0}: Validation Error: Value is not of

the correct type

javax.faces.validator.LengthValidator.MAXIMUM -- {1}: Validation Error: Value is

greater than allowable maximum of ‘’{0}’’

javax.faces.validator.LengthValidator.MINIMUM -- {1}: Validation Error: Value is less

than allowable minimum of ‘’{0}’’

javax.faces.validator.LongRangeValidator.MAXIMUM -- {1}: Validation Error: Value is

greater than allowable maximum of ‘’{0}’’

javax.faces.validator.LongRangeValidator.MINIMUM -- {1}: Validation Error Value is

less than allowable minimum of ‘’{0}’’

javax.faces.validator.LongRangeValidator.NOT_IN_RANGE={2}: Validation Error:

Specified attribute is not between the expected values of {0} and {1}.

javax.faces.validator.LongRangeValidator.TYPE -- {0}: Validation Error: Value is not of

the correct type

The following message keys are deprecated:

javax.faces.validator.NOT_IN_RANGE -- Specified attribute is not between the expected

values of {0} and {1}

JSF 应用可能通过应用配置文件的 <message-bundle> 元素提供自己的消息,或者覆盖原有的标准消息。如果 Java 平台提供的 ResourceBundle 没有消息摘要和详细信息的概念, JSF 将采用 ResourceBundle 的消息 key 来查找消息摘要。消息的详细信息则保存在和消息摘要相同的 key 并用 _detail 结尾的 key 中。这些 ResourceBundle key 用来查找相应的值来创建本地化的 FacesMessage 实例。注意消息摘要及详细信息可包含参数化的可替换标识符,这些标识符必须根据 java.text.MessageFormat 来替换成相应的值。在上面显示的消息中,将使用组件的 label 替换最后一个 ( 数字最大的 ) 参数化替换标识符。例如, {1} “DoubleRangeValidator.MAXIMUM” 的最后一个参数化替换标识符, {2} “ShortConverter.SHORT” 的参数化替换标识符。 Label 属性是一个普通的属性。请参考 3.1.10 “Generic Attributes” 8.5 “Standard HTML RenderKit 节得到更多的关于 label 属性的信息。如果这个输入组件的 label 属性没有指定,则使用组件的 client 标识符 ( client identifier ) 。这些消息可以通过 UIMessage UIMessages 组件和它们对应的标记, <h:message> <h:messages> 显示到页面上。必须使用下面的算法来根据得到 message key 创建 FacesMessage 实例。

调用当前应用Application实例的getMessageBundle()方法来判断应用是否定义了指定名字的Resource bundle。如果已定义,则载入这个ResourceBundle,并通过它来查找消息。

如果没有定义,则查找javax.faces.Messages这个resource bundle

不管哪种情况,如果消息找到,则根据上面的约定创建一个FacesMessage实例。

 

2.5.3 State Management

JavaServer Faces引入了一个强大的灵活的系统来保存及恢复请求和服务器之间视图状态。有必要从不同的观点来介绍状态管理。对于页面的作者,状态管理是透明的发生的。对于应用组装者,可以通过ServletContext InitParameterjavax.faces.STATE_SAVING_METHOD参数设置状态管理信息是保存在客户端还是服务端。这个参数指定了JSF实现的状态管理结果。

 

2.5.3.1 State Management Considerations for the Custom Component Author

组件的开发者不能在运行期得到组件状态的保存方法,但他们必须理解组件的状态管理。如 “The javax.faces.component package”节的FIGURE 4-1所示, 所有的JSF组件都实现StateHolder接口。作为一个重要的实现StateHolder的标准组件。一个自定义的直接扩展UICmponent的组件,并且没有扩展其他标准组件则需要手工实现StateHolder接口。请查看3.2.4 “StateHolder”节得到更多的信息。一个没有从标准组件扩展并且维护了自身状态的自定义组件,需要特别注意对父类的状态管理,以正确的实现StateHolder。特别的,调用saveState()必须不以任何方式改变状态。子类负责父类的状态保存和恢复。考虑这个例子,我的自定义组件表现为“slider” ui部件,同样的,它需要跟踪最大值 ,最小值,以及当前值等状态。

 

public class Slider extends UISelectOne {

protected Integer min = null;

protected Integer max = null;

protected Integer cur = null;

// ... details omitted

public Object saveState(FacesContext context) {

Object values[] = new Object[4];

values[0] = super.saveState(context);

values[1] = min;

values[2] = max;

values[3] = cur;

}

public void restoreState(FacesContext context, Object state) {

Object values[] = (Object {}) state; // guaranteed to succeed

super.restoreState(context, values[0]);

min = (Integer) values[1];

max = (Integer) values[2];

cur = (Integer) values[3];

}

注意我们在相应的地方调用了super.saveState() super.restoreState()方法。这绝对生死攸关的!如果没有成功的完成这个调用将影响组件的正常工作。

2.5.3.2 State Management Considerations for the JSF Implementor

状态管理功能的目的是让页面的作者,应用组装及组件作者的工作更为容易。然而,有些地方也存在着复杂性,JSF的实现者是一个幸运的角色。这里是一些关键参与者总的概述。请阅读javadocs文档得到每个类的更多信息。

 

Key Players in State Management

ViewHandler 状态管理系统的入口点。使用帮助类StateManager来完成它的实际工作。JSP的情景下,委派标记处理器<f:view>来完成这些功能。

StateManager 提供了状态保存的实际工作。使用帮助类ResponseStateManager来呈现特定技术的结果。

ResponseStateManager 提供呈现特定技术的状态管理结果。

UIComponent 指示处理保存和恢复每个组件的状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值