使用 JSF入门(1)

 1JSF Gossip:简介 JSF

Web应用程式的开发与传统的单机程式开发在本质上存在着太多的差异,Web应用程式开发人员至今不可避免的必须处理HTTP的细节,而HTTP无状态的(stateless)本质,与传统应用程式必须维持程式运行过程中的资讯有明显的违背,再则Web应用程式面对网站上不同的使用者同时的存取,其执行绪安全问题以及资料验证、转换处理等问题,又是复杂且难以解决的。

另一方面,本质上是静态的HTML与本质上是动态的应用程式又是一项违背,这造成不可避免的,处理网页设计的美术人员与程式设计人员,必须被彼此加入至视图元件中的逻辑互相干扰,即便一些视图呈现逻辑以标签的方式呈现,试图s展现对网页设计美术人员的亲切,但它终究必须牵涉到相关的流程逻辑。

有很多方案试着解决种种的困境,而各自的着眼点各不相同,有的从程式设计人员的角度来解决,有的从网页设计人员的角度来解决,各种的框架被提出,所造成的是各种不统一的标签与框架,为了促进产能的整合开发环境(IDE)难以整合这些标签与框架,另一方面,开发人员的学习负担也不断的加重,他们必须一人了解多个角色的工作。

JavaServer Faces  的提出在试图解决这个问题,它试图在不同的角度上提供网页设计人员、应用程式设计人员、元件开发人员解决方案,让不同技术的人员可以彼此合作又不互相干扰,它综合了各家厂商现有的技术特点,由Java Community Process(JCP)团队研拟出来的一套标准,并在2004年三月发表了JavaServer Faces 1.0实作成果。

从网页设计人员的角度来看,JavaServer Faces提供了一套像是新版本的HTML标签,但它不是静态的,而是动态的,可以与后端的动态程式结合,但网页设计人员不需要理会后端的动态部份,网页设计人员甚至不太需要接触JSTL这类的标签,也可以动态的展现资料(像是动态的查询表格内容),JavaServer Faces提供标准的标签,这可以与网页编辑程式结合在一起,另一方面,JavaServer Faces也允许您自订标签。

从应用程式设计人员的角度来看,JavaServer Faces提供一个与传统应用程式开发相类似的模型(当然因某些本质上的差异,模型还是稍有不同),他们可以基于事件驱动来开发程式,不必关切HTTP的处理细节,如果必须处理一些视觉元件的属性的话,他们也可以直接在整合开发环境上拖拉这些元件,点选设定元件的属性,JavaServer Faces甚至还为应用程式设计人员处理了物件与字串(HTTP传送本质上就是字串)间不匹配的转换问题。

从UI元件开发人员的角度来看,他们可以设计通用的UI元件,让应用程式的开发产能提高,就如同在设计Swing元件等,UI开发人员可以独立开发,只要定义好相关的属性选项来调整细节,而不用受到网页设计人员或应用程式设计人员的干扰。

三个角色的知识领域原则上可以互不干扰,根据您的角色,您只要了解其中一个知识领域,就可以运用JavaServer Faces,其它角色的知识领域您可以不用了解太多细节。

当然,就其中一个角色单独来看,JavaServer Faces隐藏了许多细节,若要全盘了解,其实JavaServer Faces是复杂的,每一个处理的环境都值得深入探讨,所以学习JavaServer Faces时,您要选择的是通盘了解,还是从使用的角度来了解,这就决定了您学习时所要花费的心力。

要使用JSF,首先您要先取得JavaServer Faces参考实作(JavaServer Faces Reference Implementation),在将来,JSF会与Container整合在一起,届时您只要下载支援的Container,就可以使用JSF的功能。

请至 JSF 官方网站的 下载区  下载参考实作,在下载压缩档并解压缩之后,将其 lib 目录下的 jar 档案复制至您的Web应用程式的/WEB-INF/lib目录下,另外您还需要 jstl.jar 与 standard.jar 档案,这些档案您可以在 sample 目录下,解压缩当中的一个范例,在它的/WEB-INF/lib目录下找到,将之一并复制至您的Web应用程式的/WEB-INF/lib目录下,您总共需要以下的档案:

  • jsf-impl.jar
  • jsf-api.jar
  • commons-digester.jar
  • commons-collections.jar
  • commons-beanutils.jar
  • jstl.jar
  • standard.jar


接下来配置Web应用程式的web.xml,使用JSF时,所有的请求都透过FacesServlet来处理,您可以如下定义:

  • web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<description>
JSF Demo
</description>
<display-name>JSF Demo</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>
javax.faces.webapp.FacesServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>


在上面的定义中,我们将所有.faces的请求交由FaceServlet来处理,FaceServlet会唤起相对的.jsp网页,例如请求是 /index.faces的话,则实际上会唤起/index.jsp网页,完成以上的配置,您就可以开始使用JSF了。
2.JSF Gossip: 第一个 JSF 程式

先看看应用程式开发人员要作些什么事,我们撰写一个简单的JavaBean:

  • UserBean.java
package onlyfun.caterpillar;

public class UserBean {
private String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}


这个Bean将储存使用者的名称,编译好之后放置在/WEB-INF/classes下。

接下来设计页面流程,我们将先显示一个登入网页/pages/index.jsp,使用者填入名称并送出表单,之后在 /pages/welcome.jsp中显示Bean中的使用者名称与欢迎讯息。

为了让JSF知道我们所设计的Bean以及页面流程,我们定义一个/WEB-INF/faces-config.xml:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/pages/index.jsp</from-view-id>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/pages/welcome.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<managed-bean>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.UserBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


在<navigation-rule>中,我们定义了页面流程,当请求来自<from-view- id>中指定的页面,并且指定了<navigation-case>中的<from-outcome>为login时,则会将请求导向至<to-view-id>所指定的页面。

在<managed-bean>中我们可以统一管理我们的Bean,我们设定Bean物件的存活范围是session,也就是使用者开启浏览器与程式互动过程中都存活。

接下来要告诉网页设计人员的资讯是,他们可以使用的Bean名称,即<managed-bean-name>中设定的名称,以及上面所定义的页面流程。

首先网页设计人员撰写index.jsp网页:

  • index.jsp
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>第一个JSF程式</title>
</head>
<body>
<f:view>
<h:form>
<h3>请输入您的名称</h3>
名称: <h:inputText value="#{user.name}"/><p>
<h:commandButton value="送出" action="login"/>
</h:form>
</f:view>
</body>
</html>


我们使用了JSF的core与html标签库,core是有关于UI元件的处理,而html则是有关于HTML的进阶标签。

<f:view>与<html>有类似的作用,当您要开始使用JSF元件时,这些元件一定要在<f: view>与</f:view>之间,就如同使用HTML时,所有的标签一定要在<html>与< /html>之间。

html标签库中几乎都是与HTML标签相关的进阶标签,<h:form>会产生一个表单,我们使用<h: inputText>来显示user这个Bean物件的name属性,而<h:commandButton>会产生一个提交按钮,我们在action属性中指定将根据之前定义的login页面流程中前往welcome.jsp页面。

网页设计人员不必理会表单传送之后要作些什么,他只要设计好欢迎页面就好了:

  • welcome.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>第一个JSF程式</title>
</head>
<body>
<f:view>
<h:outputText value="#{user.name}"/> 您好!
<h3>欢迎使用 JavaServer Faces!</h3>
</f:view>
</body>
</html>


这个页面没什么需要解释的了,如您所看到的,在网页上没有程式逻辑,网页设计人员所作的就是遵照页面流程,使用相关名称取出资料,而不用担心实际上程式是如何运作的。

接下来启动Container,连接上您的应用程式网址,例如:http://localhost: 8080/jsfDemo/pages/index.faces,填入名称并送出表单,您的欢迎页面就会显示了。
3.JSF Gossip: 简单的导航(Navigation)

第一个JSF程式 中,我们简单的定义了页面的流程由 index.jsp 到 welcome.jsp,接下来我们扩充程式,让它可以根据使用者输入的名称与密码是否正确,决定要显示欢迎讯息或是将使用者送回原页面进行重新登入。

首先我们修改一下UserBean:

  • UserBean.java
package onlyfun.caterpillar;

public class UserBean {
private String name;
private String password;
private String errMessage;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setPassword(String password) {
this.password = password;
}

public String getPassword() {
return password;
}

public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}

public String getErrMessage() {
return errMessage;
}

public String verify() {
if(!name.equals("justin") ||
!password.equals("123456")) {
errMessage = "名称或密码错误";
return "failure";
}
else {
return "success";
}
}
}


在UserBean中,我们增加了密码与错误讯息属性,在verify()方法中,我们检查使用者名称与密码,它传回一个字串,"failure"表示登入错误,并会设定错误讯息,而"success"表示登入正确,这个传回的字串将决定页面的流程。

接下来我们修改一下 faces-config.xml 中的页面流程定义:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/pages/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/pages/welcome.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/pages/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<managed-bean>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.UserBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


根据上面的定义,当传回的字串是"success"时,将前往 welcome.jsp,如果是"failure"的话,将送回 index.jsp。

接下来告诉网页设计人员Bean名称与相关属性,以及决定页面流程的verify名称,我们修改 index.jsp 如下:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>第一个JSF程式</title>
</head>
<body>
<f:view>
<h:form>
<h3>请输入您的名称</h3>
<h:outputText value="#{user.errMessage}"/><p>
名称: <h:inputText value="#{user.name}"/><p>
密码: <h:inputSecret value="#{user.password}"/><p>
<h:commandButton value="送出"
action="#{user.verify}"/>
</h:form>
</f:view>
</body>
</html>


当要根据verify运行结果来决定页面流程时,action属性中使用 JSF Expression Language "#{user.verify}",如此JSF就知道必须根据verify传回的结果来导航页面。

<h:outputText>可以取出指定的Bean之属性值,当使用者因验证错误而被送回原页面时,这个错误讯息就可以显示在页面上。
4.JSF Gossip: 导航规则设置

在JSF中是根据faces-config.xml中<navigation-rule>设定,以决定在符合的条件成立时,该连结至哪一个页面,一个基本的设定如下:

....
    <navigation-rule>
        <from-view-id>/pages/index.jsp</from-view-id>
        <navigation-case>
            <from-outcome>success</from-outcome>
            <to-view-id>/pages/welcome.jsp</to-view-id>
        </navigation-case>
        <navigation-case>
            <from-outcome>failure</from-outcome>
            <to-view-id>/pages/index.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>
 ....


对于JSF,每一个视图(View)都有一个独特的识别(identifier),称之为View ID,在JSF中的View ID是从Web应用程式的环境相对路径开始计算,设定时都是以/作为开头,如果您请求时的路径是/pages/index.faces,则JSF会将副档名改为/pages/index.jsp,以此作为view-id。

在<navigation-rule>中的<from-view-id>是个选择性的定义,它规定了来源页面的条件,< navigation-case>中定义各种导览条件,<from-outcome>定义当表单结果符合的条件时,各自改导向哪一个目的页面,目的页面是在<to-view-id>中定义。

您还可以在<navigation-case>中加入<from-action>,进一步规范表单结果必须根据哪一个动作方法(action method),当中是使用 JSF Expression Language 来设定,例如:

....
    <navigation-rule>
        <from-view-id>/pages/index.jsp</from-view-id>
        <navigation-case>
            <from-action>#{user.verify}</from-action>
            <from-outcome>success</from-outcome>
            <to-view-id>/pages/welcome.jsp</to-view-id>
        </navigation-case>
        ....
    </navigation-rule>
 ....


在导航时,预设都是使用forward的方式,您可以在<navigation-case>中加入一个<redirect/>,让JSF发出让浏览器重新导向(redirect)的header,让浏览器主动要求新网页,例如:

 ....
    <navigation-rule>
        <from-view-id>/pages/index.jsp</from-view-id>
        <navigation-case>
            <from-outcome>success</from-outcome>
            <to-view-id>/pages/welcome.jsp</to-view-id>
            <redirect/>
        </navigation-case>
        ....
    </navigation-rule>
 ....


您的来源网页可能是某个特定模组,例如在/admin/下的页面,您可以在<from-view-id>中使用wildcards,也就是使用 * 字元,例如:

....
    <navigation-rule>
        <from-view-id>/admin/*</from-view-id>
        <navigation-case>
            <from-action>#{user.verify}</from-action>
            <from-outcome>success</from-outcome>
            <to-view-id>/pages/welcome.jsp</to-view-id>
        </navigation-case>
        ....
    </navigation-rule>
 ....


在上面的设定中,只要来源网页是从/admin来的,都可以开始测试接下来的<navigation-case>。

<from-view-id>如果没有设定,表示来源网页不作限制,您也可以使用 * 显式的在定义档中表明,例如:

....
    <navigation-rule>
        <from-view-id>/*</from-view-id>
        <navigation-case>
        ....
    </navigation-rule>
 ....


或者是这样:
    <navigation-rule>
        <from-view-id>*</from-view-id>
        <navigation-case>
        ....
    </navigation-rule>

5.JSF Gossip: JSF Expression Language

JSF Expression Language 搭配 JSF 标签来使用,是用来存取资料物件的一个简易语言。

JSF EL是以#开始,将变数或运算式放置在 { 与 } 之间,例如:

 #{someBeanName}

 
变数名称可以是faces-config.xml中定义的名称,如果是Bean的话,可以透过使用 '.' 运算子来存取它的属性,例如:

 ...
 <f:view>
    <h:outputText value="#{userBean.name}"/>
 </f:view>
 ...

 

在JSF标签的属性上," 与 " (或'与')之间如果含有EL,则会加以运算,您也可以这么使用它:

 ...
 <f:view>
    名称, 年龄:<h:outputText
                  value="#{userBean.name}, #{userBean.age}"/>
 </f:view>
 ...

 

一个执行的结果可能是这样显示的:

 名称, 年龄:Justin, 29

 

EL的变数名也可以程式执行过程中所宣告的名称,或是JSF EL预设的隐含物件,例如下面的程式使用param隐含物件来取得使用者输入的参数:

 <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
 <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
 <%@page contentType="text/html; charset=Big5"%>
     
 <html>
 <head>
 <title></title>
 </head>
 <body>
 <f:view>
    <b> 您好, <h:outputText value="#{param.name}"/> </b>
 </f:view>

 </body>
 </html>

 

param是JSF EL预设的隐含物件变数,它代表request所有参数的集合,实际是一个java.util.Map型态物件,JSF所提供的隐含物件,大致上对应于 JSP 隐含物件,不过JSF隐含物件移除了pageScope与pageContext,而增加了facesContext与view,它们分别对应于 javax.faces.context.FacesContext与javax.faces.component.UIViewRoot。

对于Map型态物件,我们可以使用 '.' 运算子指定key值来取出对应的value,也可以使用 [ 与 ] 来指定,例如:

 ...
 <f:view>
    <b> 您好, <h:outputText value="#{param['name']}"/> </b>
 </f:view>
 ...

 

在 [ 与 ] 之间,也可以放置其它的变数值,例如:

...
 <f:view>
    <h:outputText value="#{someBean.someMap[user.name]}"/>
 </f:view>
 ...

 

如果变数是List型态或阵列的话,则可以在 [] 中指定索引,例如:

 ....
 <f:view>
     <h:outputText value="#{someBean.someList[0]}"/>
     <h:outputText value="#{someBean.someArray[1]}"/>
     <h:outputText
           value="#{someBean.someListOrArray[user.age]}"/> 
 </f:view>
 ....

 

您也可以指定字面常数,对于true、false、字串、数字,JSF EL会尝试进行转换,例如:

 ....
 <h:outputText value="#{true}"/>
 ....

 <h:outputText value="#{'This is a test'}"/>
 ....

 

如果要输出字串,必须以单引号 ' 或双引数 " 括住,如此才不会被认为是变数名称。

在宣告变数名称时,要留意不可与JSF的保留字或关键字同名,例如不可取以下这些名称:

 true false null div mod and or not eq ne lt gt le ge instanceof empty

 
使用EL,您可以直接实行一些算术运算、逻辑运算与关系运算,其使用就如同在一般常见的程式语言中之运算。

算术运算子有:加法 (+), 减法 (-), 乘法 (*), 除法 (/ or div) 与余除 (% or mod) 。下面是算术运算的一些例子:

运算式 结果
#{1} 1
#{1 + 2} 3
#{1.2 + 2.3} 3.5
#{1.2E4 + 1.4} 12001.4
#{-4 - 2} -6
#{21 * 2} 42
#{3/4} 0.75
#{3 div 4} 0.75,除法
#{3/0} Infinity
#{10%4} 2
#{10 mod 4} 2,也是余除
#{(1==2) ? 3 : 4} 4


如同在Java语法一样 ( expression ? result1 : result2)是个三元运算,expression为true显示result1,false显示result2。

逻辑运算有:and(或&&)、or(或!!)、not(或!)。一些例子为:

运算式 结果
#{true and false} false
#{true or false} true
#{not true} false


关系运算有:小于Less-than (< or lt)、大于Greater-than (> or gt)、小于或等于Less-than-or-equal (<= or le)、大于或等于Greater-than-or-equal (>= or ge)、等于Equal (== or eq)、不等于Not Equal (!= or ne),由英文名称可以得到lt、gt等运算子之缩写词,以下是Tomcat的一些例子:

运算式 结果
#{1 < 2} true
#{1 lt 2} true
#{1 > (4/2)} false
#{1 > (4/2)} false
#{4.0 >= 3} true
#{4.0 ge 3} true
#{4 <= 3} false
#{4 le 3} false
#{100.0 == 100} true
#{100.0 eq 100} true
#{(10*10) != 100} false
#{(10*10) ne 100} false


左边是运算子的使用方式,右边的是运算结果,关系运算也可以用来比较字元或字串,按字典顺序来决定比较结果,例如:

运算式 结果
#{'a' < 'b'} true
#{'hip' > 'hit'} false
#{'4' > 3} true


EL运算子的执行优先顺序与Java运算子对应,如果有疑虑的话,也可以使用括号()来自行决定先后顺序。
6.JSF Gossip: 国际化讯息

JSF的国际化(Internnationalization)讯息处理是基于Java对国际化的支援,您可以在一个讯息资源档中统一管理讯息资源,资源档的名称是.properties,而内容是名称与值的配对,例如:

  • messages.properties
titleText=JSF Demo
hintText=Please input your name and password
nameText=name
passText=password
commandText=Submit


资源档名称由basename加上语言与地区来组成,例如:

  • basename.properties
  • basename_en.properties
  • basename_zh_TW.properties


没有指定语言与地区的basename是预设的资源档名称,JSF会根据浏览器送来的Accept-Language header中的内容来决定该使用哪一个资源档名称,例如:

Accept-Language: zh_TW, en-US, en


如果浏览器送来这些header,则预设会使用繁体中文,接着是美式英文,再来是英文语系,如果找不到对应的讯息资源档,则会使用预设的讯息资源档。

由于讯息资源档必须是ISO-8859-1编码,所以对于非西方语系的处理,必须先将之转换为Java Unicode Escape格式,例如您可以先在讯息资源档中写下以下的内容:

  • messages_zh_TW.txt
titleText=JSF示范
hintText=请输入名称与密码
nameText=名称
passText=密码
commandText=送出


然后使用JDK的工具程式native2ascii来转换,例如:

 native2ascii -encoding Big5 messages_zh_TW.txt messages_zh_TW.properties

转换后的内容会如下:

  • messages_zh_TW.properties
titleText=JSF/u793a/u7bc4
hintText=/u8acb/u8f38/u5165/u540d/u7a31/u8207/u5bc6/u78bc
nameText=/u540d/u7a31
passText=/u5bc6/u78bc
commandText=/u9001/u51fa


接下来您可以使用<f:loadBundle>标签来指定载入讯息资源,一个例子如下:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=UTF8"%>

<f:view>
<f:loadBundle basename="messages" var="msgs"/>

<html>
<head>
<title><h:outputText value="#{msgs.titleText}"/></title>
</head>
<body>

<h:form>
<h3><h:outputText value="#{msgs.hintText}"/></h3>
<h:outputText value="#{msgs.nameText}"/>:
<h:inputText value="#{user.name}"/><p>
<h:outputText value="#{msgs.passText}"/>:
<h:inputSecret value="#{user.password}"/><p>
<h:commandButton value="#{msgs.commandText}"
actionListener="#{user.verify}"
action="#{user.outcome}"/>
</h:form>

</body>
</html>

</f:view>


如此一来,如果您的浏览器预设接受zh_TW语系的话,则页面上就可以显示中文,否则预设将以英文显示,也就是messages.properties的内容,为了能显示多国语系,我们设定网页编码为UTF8。

<f:view>可以设定locale属性,直接指定所要使用的语系,例如:

 <f:view locale="zh_TW">
 <f:loadBundle basename="messages" var="msgs"/>

 

直接指定以上的话,则会使用繁体中文来显示,JSF会根据<f:loadBundle>的basename属性加上<f: view>的locale属性来决定要使用哪一个讯息资源档,就上例而言,就是使用 messages_zh_TW.properties,如果设定为以下的话,就会使用messages_en.properties:

 <f:view locale="en">
 <f:loadBundle basename="messages" var="msgs"/>

 
您也可以在faces-config.xml中设定语系,例如:

 <faces-config>
    <application>
        <local-config>
            <default-locale>en</default-locale>
            <supported-locale>zh_TW</supported-locale>
        </local-config>
    </application>
 
 .....
 </faces-config>

 

在<local-config>一定有一个<default-locale>,而<supported- locale>可以有好几个,这告诉JSF您的应用程式支援哪些语系。

当然,如果您可以提供一个选项让使用者选择自己的语系会是更好的方式,例如根据user这个Bean的locale属性来决定页面语系:

 <f:view locale="#{user.locale}">
 <f:loadBundle basename="messages" var="msgs"/>

 

在页面中设定一个表单,可以让使用者选择语系,例如设定单选钮:

 <h:selectOneRadio value="#{user.locale}">
     <f:selectItem itemValue="zh_TW"
                   itemLabel="#{msgs.zh_TWText}"/>
     <f:selectItem itemValue="en"
                   itemLabel="#{msgs.enText}"/>
 </h:selectOneRadio>


 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值