JSF规范(六)

9 篇文章 0 订阅

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

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

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

7Application Integration

Previous chapters of this specification have described the component model, request state

information, and the next chapter describes the rendering model for JavaServer Faces user

interface components. This chapter describes APIs that are used to link an application’s

business logic objects, as well as convenient pluggable mechanisms to manage the execution

of an application that is based on JavaServer Faces. These classes are in the

javax.faces.application package.

Access to application related information is centralized in an instance of the Application

class, of which there is a single instance per application based on JavaServer Faces.

Applications will typically provide one or more implementations of ActionListener (or

a method that can be referenced by an action expression) in order to respond to

ActionEvent events during the Apply Request Values or Invoke Application phases of the

request processing lifecycle. Finally, a standard implementation of NavigationHandler

(replaceable by the application or framework) is provided to manage the selection of the next

view to be rendered.

7.1 Application

每一个使用JavaServer Facesweb应用都必须有一具单实例的Application对象。它能够通过调用FacesContext实例上的getApplication()方法或者调用ApplicationFactory实例上的getApplication()方法得到(参阅 7.2 “ApplicationFactory”)Application提供了应用逻辑如何和JSF实现进行交互的默认实现。高级的应用(或应用框架)可以通过JavaBeansgetterssetters属性访问一些集成对象来替换这些默认实现,在下面的各个小节里将有描述。

7.1.1 ActionListener Property

public ActionListener getActionListener();

public void setActionListener(ActionListener listener);

返回或者替换在“请求处理生命周期”的Apply Request ValuesInvoke Application phase阶段用来处理ActionEvent事件的ActionListenerJSF实现必须提供默认的ActionListener实现来执行下面的功能:

processAction()方法在返回的时候必须调用FacesContext.renderResponse()方法来绕过所有介于其间的生命周期阶段。

processAction()必须决定这个事件的下一个逻辑outcome。如下:

如果发起组件的action属性不为null,则取得MethodBinding并且调用它上面的invoke()方法来执行这个action包含的应用程序特定的处理逻辑。如果方法返回非null的值,则调用返回结果上的toString()方法并将得到的返回结果作为逻辑outcome。参阅3.2.1.1“Properties”节关于action属性的描述。

否则,返回的逻辑outcomenull

processAction()方法必须最终取得当前应用的NavigationHandler实例,并且传递逻辑outcome(根据上面的逻辑得到)NavigationHandler实例的handleNavigation()方法。

 

查看getActionListener()方法的javadocs文档来得到向后兼容性的信息。

7.1.2 DefaultRenderKitId Property

public String getDefaultRenderKitId();

public void setDefaultRenderKitId(String defaultRenderKitId);

一个应用可能通过render kit idViewHandler指定一个它所使用的RenderKit,以用来为应用输出视图。如果没有指定,ViewHandler将采用由RenderKitFactory.HTML_BASIC_RENDER_KIT指定的默认RenderKit

除非应用程序提供客户化的ViewHandler来支持一个应用的多个RenderKit实例,这个方法只可能在应用启动且所有的Faces请求被处理前被调用。这是本规范的一个限制,在将来可能会取消。

7.1.3 NavigationHandler Property

public NavigationHandler getNavigationHandler();

public void setNavigationHandler(NavigationHandler handler);

返回或者替换一个NavigationHandler实例,NavigationHandler用来处理传递给它的、从ActionListener得到的逻辑outcome (请参阅7.4“NavigationHandler”)。一个默认的实现必须提供如7.4.2 “Default NavigationHandler Implementation”节描述的功能。

 

7.1.4 StateManager Property

public StateManager getStateManager();

public void setStateManager(StateManager manager);

返回或者替换一个StateManager实例,该实例用来管理当前视图组件的“请求处理生命周期”Restore ViewRender Response阶段的状态。一个默认实现必须提供如7.6 “StateManager”所描述的操作。

7.1.5 ELResolver Property

public ELResolver getELResolver();

public void addELResolver(ELResolver resolver);

返回一个用来解析所有ELELResolver实例。这实现上是一个javax.el.CompositeELResolver 实例,它包含了5.6.2 “ELResolver for Faces”节所描述的ELResolver 实例。

 

addELResolver方法添加一个resolver实例到getELResolver()方法返回的javax.el.CompositeELResolver实例所包括的列表后面。请参阅5.6.2 “ELResolver for Faces”节里的图。

 

7.1.6 ELContextListener Property

public addELContextListener(ELContextListener listener);

public void removeELContextListener(ELContextListener listener);

public ELContextListener[] getELContextListeners();

 

addELContextListener()添加一个ELContextListener监听器到当前JSF应用中。这个监听器将在ELContext实例被创建的时候触发,并且每个请求只触发一次。

removeELContextListener()将参数指定的监听器从ELContextListeners列表中删除。如果指定的监听器是null,则这个方法将不抛出任何异常,也不执行任何操作。如果指定的监听器不在列表内,这个方法也不抛出任何异常,不执行任何操作。

 

getELContextListeners()方法返回通过addELContextListener()方法添加到监听器列表里的监听器数组。

7.1.7 ViewHandler Property

public ViewHandler getViewHandler();

public void setViewHandler(ViewHandler handler);

 

请参阅7.5 “ViewHandler”节中关于ViewHandler的描述。JSF实现必须提供默认的ViewHandler实现。但这个实现可以在第一次执行Render Response阶段前调用setViewHandler()进行替换。如果在第一次执行Render Response阶段后调用setViewHandler()方法,实现必须忽略这次调用。

 

7.1.8 Acquiring ExpressionFactory Instance

public ExpressionFactory getExpressionFactory();

返回当前应用的ExpressionFactory实例。这个实例被evaluateExpressionGet(请参阅7.1.9 “Programmatically EvaluatingExpressions”)这个方法所使用。

这个方法默认的实现只是简单的通过调用JSP容器的JspFactory.getDefaultFactory().getJspApplicationContext(servletContext).getExpressionFactory()方法返回一个ExpressionFactory实例。

 

7.1.9 Programmatically Evaluating Expressions

public Object evaluateExpressionGet(FacesContext context, String expression, Class expectedType)

得到求值表达式的值。调用getExpressionFactory().createValueExpression()并传递参数

ExpressionexpectedType。调用FacesContext.getELContext()并将它传递给ValueExpression.getValue()方法,返回结果。

当然,在某些时候可能希望直接得到ValueExpression或者MethodExpression实例。这可以通过调用getExpressionFactory()方法返回的ExpressionFactory实例上的createValueExpression()或者createMethodExpression()来完成。

 

7.1.10 Object Factories

Web应用的Application实例也充当了创建JSF对象的工厂,这些对象如components, converters,validators

 

public UIComponent createComponent(String componentType);

public Converter createConverter(Class targetClass);

public Converter createConverter(String converterId);

public Validator createValidator(String validatorId);

 

这里的每一个方法都根据请求的标识符,创建一个新的指定请求类型的对象实例1。对于每一个标识符所使用的实现类通常都是由JSF实现自动提供(本规范所描述的标准类),或者通过JSF Web应用的配置文件(请参阅10.4“Application Configuration Resources”)提供,或者嵌入到包含相应实现类的JAR文件中。

 

public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType);

 

 这个方法执行下面的行为:

在指定FacesContext的上下文中调用ValueExpression上的getValue() 方法。如果返回的结果是一个非空的UIComponent实例,则将这个结束作为方法的返回值返回。

如果getValue() 方法没有返回一个组件接口实例,则根据指定的componentType创建一个新的组件实例,将指定的ValueExpression传递给这个新建组件的setValue()方法,并且返回这个组件。

public void addComponent(String componentType, String componentClass);

public void addConverter(Class targetClass, String converterClass);

public void addConverter(String converterId, String converterClass);

public void addValidator(String validatorId, String validatorClass);

为了自定义标准JSF行为,基于JSF的应用能够注册附加的关联到类全名的标识符印射,或者替换JSF实现提供的默认印射。这些方法也用来让JSF实现根据应用配置文件里的<component>, <converter>, <validator>元素来注册印射。

 

public Iterator<String> getComponentTypes();

public Iterator<String> getConverterIds();

public Iterator<Class> getConverterTypes();

public Iterator<String> getValidatorIds();

基于JSF的应用可以要求Application实例得到注册到当前实例的components, converters, validators标识符。

 

 

1. Converters can also be requested based on the object class of the value to be converted.

 

7.1.11 Internationalization Support

下面的方法和属性允许一个应用描述它所支的locales,并且提供JSF对象创建的标准消息的替换文本。public Iterator<Locale> getSupportedLocales();

public void setSupportedLocales(Collection<Locale> newLocales);

public Locale getDefaultLocale();

public void setDefaultLocale(Locale newLocale);

 

JSF应用可以通过应用配置文件来申明它所支持的locales(并设置这些所支持的locales的默认locale)。在应用配置文件解析的时候,上面的设置方法必须被调用。每一次调用set方法,先前的值都将被覆盖。

 

public String getMessageBundle();

public void setMessageBundle(String messageBundle);

 

指定JSF实现获取对应于标准消息key的消息字符串的ResourceBundle全限定名(参见2.5.2.4

“Localized Application Messages”得到JSF所识别的标准消息key)

 

7.2 ApplicationFactory

对于每一个运行在servleportlett容器里的基于JSF web应用,都必须要有一个单实例的javax.faces.application.ApplicationFactory工厂实例能够被JSF或者程序代码获取到,通过执行如下的代码:

ApplicationFactory factory = (ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);

ApplicationFactory支持下面的一些方法:

public Application getApplication();

public void setApplication(Application application);

返回或替换当前web应用的Application实例。JSF实现必须提供一个具有7.1 “Application”节所描述行为的默认Application实例。

注意应用通常应该采用更为方便的途径来取得当前应用的Application实例,调用当前请求的FacesContext实例上的getApplication()来得到当前Application实例。

 

7.3 Application Actions

一个application action是应用提供的在“请求处理生命周”期的Apply Request Values或者the Invoke Application阶段(依赖于事件初始化的ActionSource实例上的immediate属性),用来在ActionEvent事件发生时处理应用特定功能的一些java类方法。

 

Application action不是正式的JSF API;用于代替满足下列要求的、作为action的可以通过执行方法绑定表达式(method binding expression)进行的所有方法:

方法必须是 public

方法必须没有参数。

方法必须返回一个object

action方法必须被默认的ActionListener实现所调用,就像有前面的7.1.1 “ActionListener Property”节所描述的那样。它的职责是执行应用所希望的动作,并且返回一个逻辑“outcome”以用于让NavigationHandler去确定下一个视图。调用的action方法被一个实现了ActionSource的组件的action属性指定的MethodBinding所定义。因此,一个拥有多个ActionSource组件的组件树可以分别的指定所调用的action方法,这些action既可以是相同的java类,也可以是不同的java类。

7.4 NavigationHandler

7.4.1 Overview

一个单实例的NavigationHandler对象的职责是结合当前请求的FacesContext实例所包含的状态信息来处理application action返回的逻辑outcome,并且(可选的)选择一个新视图来呈现。就如下面提到的,如果application action返回的outcomenull,则相同的视图将被重新显示。这是相同视图(或者组件树)被重用的唯一情况。

public void handleNavigation(FacesContext context, String fromAction, String outcome);

handleNavigation可以通过调用当前应用ViewHandler实例上的createView()方法来选择一个新的视图,随意的定制创建的视图,并且通过调用传入的FacesContext实例上的setViewRoot()方法来选择这个视图。作为一种选择,NavigationHandler能够完成实际的响应(例如,发出HTTP redirect),并且调用FacesContext实例上的responseComplete()方法。

NavigationHandler 返回后,控制通常都进入“请求处理生命周期”的 Render Response 阶段 ( 请参阅 2.2.6 “Render Response” ) ,这将引起新选择的视图被呈现。如果 NavigationHandler 调用了 FacesContext 实例上的 responseComplete() 方法,则 Render Response 阶段将被跳过。
7.4.2 Default NavigationHandler Implementation

JSF必须提供印射用来调用application actionaction引用,application action返回的outcome,及状态信息到新选择的视图的viewId的默认实现。在本节的剩余部分将描述默认实现提供的功能。

默认NavigationHandler实现的行为可以通过0个或者多个应用配置文件在web应用启动的时候进行配置(请参阅10.4 “Application Configuration Resources”)。配置信息表现为0个或者多个<navigation-rule>元素,每个键入的viewId匹配模式在<from-viewid>元素中表达。如果你采用默认的ViewHandler,则这个匹配模式要么必须完全匹配viewId(”/index.jsp”),要么是组件的view id后加”*”字符。如果一个匹配表达式是”*”,或者在<navigation-rule>规则里缺乏<from-view-id>元素,则表示这个规则匹配所有的组件view id

<navigation-rule>元素里包含了一0个或者多个<navigationcase>元素,这些元素包含了附加的基于用来调用application action(如果存在)action引用表达式值的匹配条件,和调用application action2invoke()方法的得到逻辑outcome<navigation-case>包含了一个<to-view-id>元素,这个元素内容是选择出来的保存在当前请求FacesContext里的view Id。请看下面的例子来得到NavigationHandler必须配置的配置信息。

 

2. It is an error to specify more than one <navigation-case>, nested within one or more <navigation-rule> elements with the

same <from-view-id> matching pattern, that have exactly the same combination of <from-xxx> element values.

允许使用默认NavigationHandler的应用配置文件为每一个相同的<from-view-id>匹配模式包含超过一个的<navigation-rule>元素。下面描述的算法可以完成这个目标,所有包含在同一个<navigation-rule>里的<navigation-case>元素应该作相同的处理。

 

默认的NavigationHandler实现在执行下面的算法时应该具有相同的行为(虽然可能使用一些优化的技术实现)

如果传递给handleNavigation()方法的逻辑outcomenull,则不需要进行匹配规则的描述。这表示当前视图将被重新显示。

 

找出其中的<from-view-id>指定的匹配模式和当前viewId(包含在当前请求的FacesContext里的视图)相匹配的<navigation-rule>元素。Rule实例将以下列的顺序被考虑。

viewId完全匹配的不以”*”号结尾的<from-view-id>匹配模式。

以星号结尾的且星号前面部分完全匹配viewId前面部分相匹配的<from-view-id>匹配模式。如果有多个navigation rules匹配,则取那个前缀匹配最长的那个。 If the patterns for

multiple navigation rules match, pick the longest matching prefix first.

如果一个<navigation-rule>包含的<from-view-id>模式只是一个星号3,则表示它可以匹配任何view id

 

对于匹配的<navigation-rule>所包含的<navigation-case>元素,根据传入给handleNavigation()方法的fromaActionfromOutcome参数查找匹配的<from-action><from-outcome>方式来查找。Navigation cases根据下面的顺序检查:

指定的<from-action>值和<from-outcome>值都完全和传递给handleNavigation()方法的actionoutcome参数相匹配(两个参数不能为null,并且两个参数都等于对应的条件值)

指定的<from-outcome>值和传递给handleNavigation()方法的outcome参数相匹配(outcome不能为null,并且等于对应的条件值)。

只有一个<from-action>的值和传递给handleNavigation()方法的action表达式相匹配(action不能为null,并且等于对应的条件值)

检查其他剩余的<navigation-case>是否匹配。

如果找到一个匹配的<navigation-case>元素,并且在这个<navigation-case>元素里没有指定<redirect/>元素(或者应用运行在Portlet环境中,不能进行redirects),则根据匹配的navigation case里的<to-view-id>元素值来请求当前应用的ViewHandler生成一个新的UIViewRoot实例。然后,退出算法。

如果找到一个匹配的 <navigation-case> 元素,并且在这个 <navigation-case> 元素里指定了 <redirect/> 元素,并且应用没有运行在 Portlet 环境中,则根据匹配的 navigation case 里的 <to-view-id> 元素来为这个 viewId 构造一个 context-relative 的路径,然后让当前响应执行 HTTP redirect 来重定向到这个路径上,并且调用当前请求的 FacesContext 实例上的 responseComplete()

如果没有找到匹配的<navigation-case>元素,则返回到第一步并且查找下一个匹配的<navigation-rule>元素(如果有)。如果没有找到其他匹配的rule元素,则不任何改动的返回当前页面。

一个新的rule匹配都将引起一个新的视图被创建,并且老视图的状态将丢失。

3. Or, equivalently, with no <from-view-id> element at all.

7.4.3 Example NavigationHandler Configuration

下面的<navigation-rule>可以出现在一个或多个应用配置文件中(请参阅10.4 “Application Configuration Resources”),用来配置NavigationHandler默认实现的行为。

 

<navigation-rule>

<description>

APPLICATION WIDE NAVIGATION HANDLING

</description>

<from-view-id> * </from-view-id>

<navigation-case>

<description>

Assume there is a “Logout” button on every page thatinvokes the logout Action.

</description>

<display-name>Generic Logout Button</display-name>

<from-action>#{userBean.logout}</from-action>

<to-view-id>/logout.jsp</to-view-id>

</navigation-case>

<navigation-case>

<description>

Handle a generic error outcome that might be returnedby any application Action.

</description>

<display-name>Generic Error Outcome</display-name>

<from-outcome>loginRequired</from-outcome>

<to-view-id>/must-login-first.jsp</to-view-id>

</navigation-case>

</navigation-rule>

 

<navigation-rule>

<description>

Assume there is a search form on every page. These navigation cases get merged with the application-wide rules above because they use the same “from-view-id” pattern. The same thing would also happen if “from-view-id” was omitted here, because that is equivalent to a matching pattern of “*”.

</description>

<from-view-id> * </from-view-id>

<navigation-case>

<display-name>Search Form Success</display-name>

<from-action>#{searchForm.go}</from-action>

<from-outcome>success</from-outcome>

<to-view-id>/search-results.jsp</to-view-id>

</navigation-case>

<navigation-case>

<display-name>Search Form Failure</display-name>

<from-action>#{searchForm.go}</from-action>

<to-view-id>/search-problem.jsp</to-view-id>

</navigation-case>

</navigation-rule>

 

<navigation-rule>

<description>

Searching works slightly differently in part of the site.

</description>

<from-view-id> /movies/* </from-view-id>

<navigation-case>

<display-name>Search Form Success</display-name>

<from-action>#{searchForm.go}</from-action>

<from-outcome>success</from-outcome>

<to-view-id>/movie-search-results.jsp</to-view-id>

</navigation-case>

<navigation-case>

<display-name>Search Form Failure</display-name>

<from-action>#{searchForm.go}</from-action>

<to-view-id>/search-problem.jsp</to-view-id>

</navigation-case>

</navigation-rule>

 

7.5 ViewHandler

ViewHandler是一种允许实现者或者基于JSF的应用在“请求处理生命周期”的Render Response Restore View阶段添加自己处理活动的插件机制。它允许实现支持不同的响应生成技术,也包括不同的状态保存/恢复途径。

一个JSF实现必须提供默认的ViewHandler实现。请参阅7.1.7 “ViewHandler Property”节,得到关于替换默认实现的信息。

 

7.5.1 Overview

ViewHandler定义了下面段落所描述的一些公共的API

 

public Locale calculateLocale(FacesContext context);

public String calculateRenderKitId(FacesContext context);

这些方法在createView()方法里被调用,以决定后续所有请求所采用的Locale,并且找出哪一个renderKitId用来呈现当前视图。

 

public void initView(FacesContext) throws FacesException;

public String calculateCharacterEncoding(FacesContext context);

initView() 必须是 “请求处理生命周期”的 Restore View 阶段在完成 FacesContext 里的参数检查后 被立即调用的第一个方法,默认的 initView() 方法实现调用 calculateCharacterEncoding() 方法,如果这个方法返回 non-null initView() 通过 ExternalContext 上的 setRequestCharacterEncoding() 方法来设置当前请求的字符编码。

public UIViewRoot createView(FacesContext context, String viewId);

创建并返回一个新的UIViewRoot实例。根据FacesContext里指定的信息初始化这个实例并确保设置viewIdUIViewRoot实例的viewId属性中。

 

public String getActionURL(FacesContext context, String viewId);

返回一个经过适当编码和处理的URL,这个URL(如果被激活)将引起JSF执行指定viewId的“请求处理生命周期”。

 

public String getResourceURL(FacesContext context, String path);

返回一个经过适当编码和处理的URL,这个URL(如果被激活)将可以取到指定的web应用资源。

 

public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException;

这个方法必须在“请求处理生命周期”的Render Response 阶段被调用。它必须提供一个有效的保存在当前请求的FacesContext里的ResponseWriterResponseStream实例(请参阅6.1.7“ResponseStream and ResponseWriter”),然后将保存在FacesContext实例里的viewRoot用相应的writerstream呈现出来。它也影响关联的StateManager(请参阅7.6 “StateManager”),通过调用getSerializedView()saveView()方法,以确保当前视图的状态信息保存到请求中。

 

public UIViewRoot restoreView(FacesContext context, String viewId)throws IOException;

这个方法必须在“请求处理生命周期”的 Restore View 被调用。它必须执行恢复关联到特定的 FacesContext viewId 视图所要求的行为。

它的调用者必须确保将返回的UIViewRoot实例保存到FacesContextviewRoot属性中。另外,如果restoreView()方法返回null(因为这个viewId没有保存的状态信息),调用者必须调用createview()方法,并且调和FacesContext实例上的renderResponse()方法。

 

public void writeState(FacesContext context) throws IOException;

Take any appropriate action to either immediately write out the current view’s state

information (by calling StateManager.writeState()), or noting where state

information may later be written. 为了让ViewHandler有保存每一个提交的form里包含的状态的机会,这个方法必须在每次调用UIForm组件的encodeEnd()方法时被调用一次。

 

7.5.2 Default ViewHandler Implementation

在下面轮流使用的术语view identifierviewId指的是用来处理视图的应用资源的context-relative路径,就像JSP文件一样。在JSP的情况下,这个就是JSP所表现的视图的相对路径,如/foo.jsp

 

JSF实现必须提供默认的ViewHandler实现,用来呈现包含JSF组件的JSP页面,它必须具有下面各节所描述的行为:

calculateCharacterEncoding()方法必须履行下面的职责:

检查request header里的Content-Type。如果它有charset参数则分解出它的字符集并返回。

如果没有,调用 FacesContext ExternalContext 上的 getSession(false) 方法,测试 session 是否已存在。如果 session 已存在,则检查 ExternalContext.getSessionMap() 返回的 Map 里包含的 Key 为字符串常量 javax.faces.application.ViewHandler.CHARACTER_ENCODING_KEY 的值。如果找到这个值,则将它转换为字符串并返回。

calculateLocale()方法必须履行下面的职责:

为当前请求尝试从ExternalContextgetLocales()返回的locales找到一个匹配的locale,返回的Locales是根据定义在应用配置文件里所支持的locale得到。匹配的方法根据JSTL规范的JSTL. 8.3.2节所描述的算法进行。如果找到匹配的,则返回对应的Locale对象。

否则,如果应用在配置文件里指定了一个默认的locale,则返回这个默认的Locale对象。

 

calculateRenderKitId()方法必须履行下面的职责

如果符号常量ResponseStateManager.RENDER_KIT_ID_PARAM 指定的request参数(request parameter)值不是null,则返回这个值。

否则,如果Application.getDefaultRenderKitId()的返回值不为null,则返回这个值。

 

createView()方法必须履行下面的职责:

用下面的算法计算当前请求对应的viewId

如果FacesServlet采用的是前缀印射(如“/faces/*),则viewId为当前请求URI的扩展路径信息。

如果 FacesServlet 采用的是后缀印射 ( 如“ *.faces ) ,则 viewId 为当前请求 URI servlet 路径信息并加上 context 初始化常量 ViewHandler.DEFAULT_SUFFIX_PARAM_NAME( 如果没有配置这样的 context 初始化参数,则使用默认的符号常量 ViewHandler.DEFAULT_SUFFIX 作为后缀 ) 作为后缀后的值。

如果不能得到viewId,或者viewId完全等servlet mapping,则调用ExternalContext实例上的redirect()方法,并传递当前应用的相对路径。

创建一个新的UIViewRoot对象实例。

为当前请求有条件的从当前视图里拷贝renderKitIdlocale (就像在Javadocs里对 createView()方法的描述)

返回新创建的UIViewRoot

 

getActionURL()方法必须履行下面的职责:

如果指定的viewId不是以“/”开始,则抛出IllegalArgumentException异常。

如果FacesServlet采用前缀印射(“/faces/*”),则在viewId前面加上当前应用的相对路径及指定的前缀,并返回这个相加后的值。如 “/cardemo/faces/chooseLocale.jsp”

如果FacesServlet采用的是后缀印射( “*.faces”),并且指定viewId以指定的后缀结尾,则用符号常量ViewHandler.DEFAULT_SUFFIX_NAME(如果没有配置这样的context初始化参数,则使用默认的符号常量ViewHandler.DEFAULT_SUFFIX作为后缀)指定的context初始化参数替换后缀指定的后缀,并且在替换后缀后的值的前面加上当前应用的相对路径,然后返回这个处理后的值。如/cardemo/chooseLocale.faces

 

getResourceURL() 方法必须履行下面的职责:

如果指定的路径以“/”开始,则在路径前加上当前应用的相对路径,并返回这个结果。

否则,不作任何修改的返回传入的路径值。

 

initView()方法必须履行下面的职责:

调用 calculateCharacterEncoding()方法。如果返回结果不是null,则传递这个非null的结果到FacesContextExternalContext上的setRequestCharacterEncoding()方法中。

 

renderView()方法必须履行下面的职责:

如果当前请求是ServletRequest,则调用javax.servlet.jsp.jstl.core.Config类上的set()方法,传递当前ServletRequest,符号当量Config.FMT_LOCALE,和指定UIViewRoot 上的locale属性。这为当前响应配置应用最佳的locale

如果FacesServlet采用的是后缀印射(”*.faces”),则检查指定的UIViewRoot上的viewId属性。如果它以相匹配的后缀结尾,则修改它的后缀,使用符号常量ViewHandler.DEFAULT_SUFFIX_NAME 指定的context初始化参数替换它的后缀(如果没有配置这样的context初始化参数,则使用默认的符号常量ViewHandler.DEFAULT_SUFFIX作为后缀)

取得 UIViewRoot 里的 locale ,用它更新 request scope 里的 JSTL locale 属性。这个属性必需在 JSTL setBundle 标记被调用之前被更新,因为一个新的 LocalizationContext 对象需要根据这个 locacle 被创建。

根据ExternalContext创建当前response的包装器对象,并且将它作为一个新的response设置ExternalContext中。这个包将器必须缓冲所有写入到响应里的内容,以准备在后面的输出。有必要允许出现在页面里的<f:view>标记后的任何内容。

viewId作为context-relative路径(”/”开始),并传递viewIdExternalContext以象的dispatch()方法,执行对应的JSP页面来创建视图。这导致将控制传递给JSP容器,然后再传到UIComponentClassicTagBase。请参阅UIComponentClassicTagBasejavadoc文档来得到在执行JSP页面时如何处理视图创建的详细信息。

以线程安全的方式将下面使用到的,包装后的response保存起来。默认的实现将它保存在request scope中。

将初始response恢复到ExternalContext里。

如果FacesContext有一个非nullResponseWriter,则调用它的cloneWithWriter()方法,并传递当前responseWriter对象作为参数,创建一个新的writer对象。否则,使用当前RenderKit来创建一个新的ResponseWriter

设置这个新的ResponseWriterFacesContext里,并保存老的那个。

调用 StateManager 上的 saveView() 方法,然后将结果以线程安全的方式保存起来,这个结果将在调用 ViewHandler.writeState() 方法的时候使用。

调用ResponseWriter上的startDocument()方法。

调用UIViewRoot上的encodeAll()方法。

将封装的response里的全部内容输出,并从线程安全的存储器里移除这个封装的response对象。

如果老的ResponseWriter不是null,则将这个老的ResponseWriter放回到FacesContext里。

 

restoreView()方法必须履行下面的职责:

采用和createView()方法相同的算法计算当前请求对应的viewId

如果没有viewId可以被得到,则返回null

调用对应的StateManager上的restoreView()方法,传递当前请求的FacesContext实例和计算得到的viewId,返回UIViewRoot对象,也可能返回null

 

writeState()方法必须履行下面的职责:

将在调用renderView()方法里得到的、以线程安全的方式保存起来的状态取出,并传递这个状态到StateManagerwriteState()方法中。

 

在非JSP的应用中,这些职责必须被客户化的ViewHandler实现所执行。

 

7.6 StateManager

StateManager 起到在两个请求之间保存和恢复视图的作用。应用的 StateManager 实例是从 Application 实例中得到,因此它不知道用来呈现视图的 RenderKit 所生成的标记语言详细信息。 所以 StateManager 是一个帮助类 ( 请参阅 8.3 “ResponseStateManager” ) ,它由 RenderKit 实现提供并且对标记语言的详细信息敏感。 JSF 实现提供默认的 StateManager 实现来支持下面所描述的行为。
7.6.1 Overview

概念上,视图的状态可以被分成两个部分:

Tree Structure. 这包括组件的父子关系,包括facets

Component State. 包括:

组件的特征和属性,及

Validators, Converters, FacesListeners, 及其它关联到组件的对象。这些关联对象根据组件实现的方式进行保存。这些关联的对象可能拥有状态,提供的StateHolder接口(请参阅3.2.4 “StateHolder”)允许这些对象保存自己的特性和属性。如果一个关联对象没有实现StateHolder接口,但它实现了Serializable,则它采用标准的序列化进行保存。如果一个关联对象既没有实现StateHolder接口,又没有实现Serializable接口,则它必须提供一个public的,没有参数的默认构造器,且这个对象的仅仅用它的构造器的初始化来恢复它的默认状态4

将树结构和树状态分离具有一定的好处,它允许实现采用不同的机制来保存树的结构信息和状态信息。例如:系统可以以静态的方式保存树结构,如XML文件,系统可以将树以DOM的形式保存在内存中,可以让应用的所有请求保用。

 

 

4. The implementation classes for attached object must include a public zero-arguments constructor.

7.6.2 State Saving Alternatives and Implications

JSF实现根据javax.faces.STATE_SAVING_METHOD(参阅10.1.3“Application Configuration Parameters”)初始化参数支持两种主要机制来保存状态。

参数指定的值指出了系统保存状态的途径,允许JSF实现在技术细节上进行革新:

client 将状态包含在发送给客户端的标记文本里 ( HTML 的隐藏域 ) 。这些状态信息必须包含在后续的请求里,以便 JSF 在没有服务端保存状态的情况下恢复视图。在信息被发向客户时 ( 这些信息在某些时候被持久化 ) ,对这些信息进行加密以防止被篡改是明智的。

server 将请求间的状态保存在服务端。如果实现者期望保存的状态在不同的容器里具有容错(fail over)能力,则在实现服务端状态保存策略时,一直要保留这个期望在脑子里。默认实现序列化视图在clientserver两种模式。在server模式里,这个被序列化的视图被保存在session里,并且取得这个视图的唯一key被发送到客户端。在保存序列化的视图在session里的情况下,容错将采用容器提供的机制。

所有的组件特性和属性值(也包括要作为状态保存的关联对象)都必须实现java.io.Serializable

7.6.3 State Saving Methods.

public Object saveView(FacesContext context);

这个方法将收集包含在FacesContext里的视图对应的树结构及组件状态收集保存起来,并且返回一个实现java.io.Serializable接口的java.lang.Object 。如果这个方法返回null,则表示没有状态被保存。

这个返回的对象代表了视图的全部状态,这样一个“请求处理生命周期”就可以根据它运行于postback状态下。特别要注意的是要保证组件实例的关联对象,如listeners, converters, validators也一起被保存。StateHolder接口因这种原因而提供。

这个方法也强制要求组件的idNamingContainer里是唯一的。

 

public void writeState(FacesContext context, Object state) throws

IOException;

依赖于实现方式,保存指定的状态对象。

7.6.4 State Restoring Methods

public UIViewRoot restoreView(FacesContext context, String viewId);

依赖于实现方式,恢复指定viewId对应的视图的树结构及组件状态。如果指定的viewId没有对应的保存的状态信息,方法返回null

这个方法的默认实现调用 restoreTreeStructure ,并且如果必要调用 restoreComponentState()
7.6.5 Convenience Methods

public boolean isSavingStateInClient(FacesContext context);

方法仅仅在ServletContext的初始化参数StateManager.STATE_SAVING_METHOD_PARAM_NAME 的值等于常量STATE_SAVING_METHOD_CLIENT时返回true。否则返回false

 

7.7 Deprecated APIs

7.7.1 PropertyResolver Property

public PropertyResolver getPropertyResolver();

[deprecated]

public void setPropertyResolver(PropertyResolver resolver);

[deprecated]

getPropertyResolver()必须返回一个封装了ELResolver对象的PropertyResolver实例。PropertyResolver实例用来在处理值表达式时计算.[]操作符。这个方法被deprecated,替代方法为getELResolver()(请参阅7.1.5“ELResolver Property”)

setPropertyResolver()设置PropertyResolver实例,这个实例用来在处理值表达式时计算.[]操作符。必须提供一个默认的实现,这个实现要提供如5.8.2“PropertyResolver and the Default PropertyResolver”所描述的操作。这个方法被deprecated。请参阅Javadocs文档得到setPropertyResolver()方法的更多信息。

7.7.2 VariableResolver Property

public VariableResolver getVariableResolver();

[deprecated]

public void setVariableResolver(VariableResolver resolver);

[deprecated]

getVariableResolver() 必须返回一个封装了 ELResolver 对象的 PropertyResolver 实例。 VariableResolver 实例用来转换值表达式的第一个名称到一个对象。实现在调用 ELResolver 上的任何方法时必须传递 null 作为 base 参数。这个方法被 deprecated ,替代方法为 getELResolver ()
setVariableResolver 替换用来解决方法和值绑定的 VariableResolver 实例。必须提供一个默认的实现,这个实现要提供如 5.8.1 “VariableResolver and the Default VariableResolver” 所描述的操作。 请参阅 Javadocs 文档得到 setVariableResolver () 方法的更多信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值