2.4 解读JSF配置
与所有Java框架一样,JSF也是非常依赖于XML配置文件的。对于大部分JSF初级开发者而言,他们常做的就是两件事情:定义托管Bean,配置XML配置文件。本节将会介绍JSF配置的基本知识,包括配置JSF核心控制器的详细知识和JSF配置文件的基本结构。
2.4.1 配置核心控制器(FacesServlet)
所有Web应用都是请求—响应架构的,因此Web应用都是用户请求驱动的,当用户向Web应用发送请求之后,Web应用就会处理该请求,处理完成后将响应送回客户端。
对于传统的、基于Servlet模式的MVC框架(如Struts),它们基本上只是对传统Web编程进行了简化,它的简化流程图如图2.8所示。
图2.8 传统MVC框架的简化流程图
对于传统的MVC框架而言,它的大量工作都由核心控制器完成,如图2.8所示。当使用这种MVC框架时,开发者依然需要非常清楚请求—响应的流程,只是由于MVC框架的核心控制器为我们完成了大部分工作,因此开发者开发业务控制器更加简单。
前面分析JSF和传统的MVC框架时已经指出,JSF框架与传统的MVC框架的最大差别在于:它不再基于请求-响应,它是以事件响应机制来进行通信的,它可以将视图页面的UI组件的状态绑定到托管Bean,也可以通过视图页面中UI组件的事件来触发托管Bean的方法……但这一切只是开发者眼中的表象,只是JSF封装后给开发者看到的现象。
JSF也只是一个MVC框架,它依然无法改变Web应用请求-响应的基本流程。因此为了让用户请求被JSF处理,JSF也提供了一个核心控制器来负责处理所有的用户请求,这就是前面示例中看到的javax.faces.webapp.FacesServlet,它就是JSF的核心控制器。
FacesServlet是一个标准的Servlet,因此配置它与配置普通的Servlet没有太大的差别,同样是先配置Servlet,再配置Servlet映射的URL。例如如下代码片段:
<!-- 配置JSF的核心控制器:FacesServlet --> <servlet> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- 配置JSF核心FacesServlet的映射 --> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping>
上面的配置片段指定使用FacesServlet来拦截所有以.jsf结尾的请求。需要指出的是,此处配置FacesServlet拦截的URL不一定需要是*.jsf,完全可以由用户随意定义,例如*.faces、*.do等。
为JSF配置了核心控制器FacesServlet之后,可能还需要为JSF框架指定更多额外的配置参数,为JSF指定配置参数通过在web.xml文件中使用<context-param.../>元素配置即可。
提示
<context-param.../>元素用于为整个Web应用配置参数,而这些参数到底会发生怎样的作用则取决于应用本身。关于<context-param.../>元素的配置细节,Web应用如何读取它配置的参数,请参考疯狂Java体系的《轻量级Java EE企业应用实战》一书中关于application内置对象的介绍。当我们在web.xml中使用<context-param.../>元素配置多个参数之后,这些参数将会由JSF框架来读取,从而对JSF框架产生作用。
例如,下面我们就为JSF指定了程序状态的保存位置。
<!-- 配置JSF程序状态的保存位置 -->
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<!-- 将程序状态保存在客户端 -->
<param-value>client</param-value>
</context-param>
从上面配置可以看出,通过<context-param.../>元素配置参数就是指定参数名(由 <param-name.../>元素值指定)和参数值(由 <param-value.../>元素值指定)——每个<context-param.../>元素只可为JSF配置一个参数。
我们可以在web.xml文件中使用无数<context-param.../>元素来配置参数,但如果JSF不去读取这些参数,那么这些参数将对JSF没有任何意义。JSF是根据参数名来读取这些参数的,如果没有读到某个参数,JSF将按默认值来处理该参数。
对JSF有效的参数名及其详细作用的说明如下:
javax.faces.STATE_SAVING_METHOD:该参数指定JSF应用状态的保存位置。Web应用本身是基于请求-响应架构的,因此它本质上是状态不连续的。而JSF为了实现在多个请求之间保存和恢复应用状态,必须将应用状态保存在某个位置——该位置由该参数指定,该参数值可以是client或server。对JSF RI而言,该参数的默认值是server。
· 如果用户选择client,表明状态保存在客户端。此时应用状态保存在页面上的隐藏字段中。大部分时候,建议将状态保存在客户端,这样既可以降低客户端和服务器端的通信成本,还可以保证即使服务器重启,应用状态也不会丢失。
· 如果用户选择server,表明状态保存在服务器端,此时应用状态保存在session中。
注意
笔者也看过不少关于JSF的图书和资料,比如《The Java EE 5 Tutorial》(国内译名:《Java EE 5权威指南》)一书中说JSF实现默认将状态保存在客户端(原文:The JavaServer Faces implementation saves the state on the client by default),但实际上JSF将应用状态到底是保存在客户端还是服务器,我们只要动手试一下就知道了,读者千万不要被误导。
javax.faces.DEFAULT_SUFFIX:该参数指定JSF映射视图资源时的默认后缀。该参数的默认值是.jsp。大部分情况下,不需要改变该参数的值。关于该参数的作用见本节小示例的说明。
javax.faces.LIFECYCLE_ID:该参数指定JSF所管理的生命周期实例的标识符,该参数通常无须修改。关于JSF生命周期的概念本书后面将有更详细的介绍。
javax.faces.CONFIG_FILES:该参数指定JSF配置文件的保存位置。在默认情况下,JSF会自动加载位于WEB-INF/路径下的faces-config.xml文件。如果应用中包含多个JSF配置文件,则需要指定该参数;如果应用中只有一个JSF配置文件,且文件为位于WEB-INF路径下的faces-config.xml文件,则可以省略配置该参数。
com.sun.faces.verifyObjects:该参数用于指定是否需要验证自定义组件。当JSF应用中定义了自定义组件、转换器、校验器时,可以设置应用启动时验证这些自定义组件。该参数的值只能是true或false。
com.sun.faces.validateXml:该参数用于指定是否验证JSF应用中的XML文件。
com.sun.faces.NUMBER_OF_VIEWS_IN_SESSION:当我们设置在服务器端保存应用状态时,该参数控制session中所保存的视图数量。设置为-1表示没有限制。
为了解释JSF配置参数中javax.faces.DEFAULT_SUFFIX参数的作用,我们对前面介绍的jsfqs应用稍作修改,在web.xml文件中增加如下片段。
程序清单:codes\02\2.4\default_suffix\WEB-INF\web.xml
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<!-- 指定JSF映射视图资源时默认后缀是.html -->
<param-value>.html</param-value>
</context-param>
在web.xml文件中增加DEFAULT_SUFFIX配置参数之后,同样向该应用的login.jsf发送请求将看到如图2.9所示的效果。
图2.9 设置javax.faces.DEFAULT_SUFFIX参数的作用
2.4.2 JSF配置文件结构
正如前面示例中看到的,JSF应用可以使用一个或多个配置文件来管理JSF托管Bean、导航规则等,这些都是JSF开发者经常需要处理的工作。习惯上,我们会将JSF配置管理分到多个配置文件中进行管理,这样就可让不同的配置文件管理不同的配置工作。
JSF配置文件的根元素都是<faces-config.../>元素,JSF配置文件的结构如图2.10所示。
图2.10 JSF配置文件的结构
从图2.10可以看出,JSF根元素<faces-config.../>下一共可以配置11个配置元素,其中<faces-config-extension.../>元素用于对JSF进行非常规扩展,并不常见。其他10个配置元素最常用的就是:
<managed-bean.../>:JSF应用中所有的托管Bean都在该元素下配置、管理。
<navigation-rule.../>:该元素用于管理JSF应用的导航规则。
上面这两个元素是JSF开发者最熟悉的两个元素。除此之外,JSF的其他配置元素大致可以分为如表2.1所示的3类。
表2.1 JSF配置元素
此处只要求读者熟悉JSF配置文件的基本结构,大致了解一下JSF配置文件中的常见配置元素。关于这些配置元素的具体用法,后面会有更详细的介绍。
对开发者来说,如果希望在程序中显式获取该文件中的配置信息,则可通过JSF提供的Application对象来访问,该对象提供了大量的方法来访问、动态改变faces-config.xml文件的配置。Application对象代表JSF应用本身,整个JSF应用都共享一个Application对象,所以它是线程安全的,通常可通过ApplicationFactory的getApplication()方法来获取该对象。下一章将会看到通过该对象来访问应用中自定义消息资源包baseName的示例,故此处不再赘述。