本文是本人要出版的JSP书中的一章,因为培训内容和本章重复,所以直接上传过来,可能格式有些变化。
如果要转发请注明如下信息:
本文是《Java Web程序设计基础教程》一书的样章 作者:李绪成,[email protected]。
目标:
u 掌握Java Web应用的国际化;
u 掌握页面信息中数字的格式化;
u 掌握页面信息中日期和时间的格式化。
随着全球经济的国际化,很多公司的业务都涉及多个国家和多种语言,这就要求公司的Web应用同时支持多种语言,系统会根据您所使用的语言来确定使用哪种语言为您服务,称为国际化。例如,您使用的操作系统是中文的,您看到的网站将是中文版的。如果您使用的操作系统是日文版的,您看到的网站将是日文版的。本章实现了用户管理界面的国际化。
11.1 目标演示
11.1.1 功能描述
前面完成的用户管理界面使用的是中文。现在希望用户可以选择自己的语言,如果选择中文,则显示中文界面,如果用户选择英文,则显示英文界面。如果用户没有选择,则根据用户浏览器的默认语言显示。
11.1.2 运行效果
如果读者的浏览器的默认语言是中文,看到的用户管理界面如图11.1所示。如果读者的浏览器的默认语言是英语,看到的用户管理界面如图11.2所示。
图11.1 默认的用户管理界面
图11.2 用户选择English时候的界面
两个界面的相同之处是界面中的所有动态信息是相同的,也就是用户信息是相同的。不同之处在于页面的静态信息,图11.1中的静态信息是中文,图11.2中的静态信息是英文。
进入这个界面之后用户可以任意的选择语言。选择“中文”看到如图11.1所示界面,选择“English”能够看到如图11.2所示的界面。
11.1.3 思路分析
要想使网站同时支持中文和英文,最直接的想法可能就是编写两个网站,一个使用英文,一个使用中文。从实现上来说,没有任何问题。但是在完成这两个网站的时候,您会发现两个网站的大部分内容是相同的,例如格式、功能、信息等,只有少数信息是不同的,就是给用户的提示信息。例如,在用户管理界面上,基本格式完全相同,用户信息也是相同的,上面的功能也完全相同,不同的是给用户的提示信息不同,中文可能会使用“用户名”,英文可能会使用“Username”。
从软件的开发和维护上来说,如果能够共享这些相同的功能是最好了,然后把不同的信息放在不同的文件中,需要的时候从这些文件中调用不相同的部分。这样维护起来就非常方便,一旦某一天网站需要支持日文,只需要编写一个存储日文信息的文件即可,如果功能发生改变,只需要修改一个版本即可。这就是国际化的基本思路。
从上面的分析,可以看出要完成国际化,需要做以下几件事情:
l 编写资源文件:把网站中需要使用不同语言显示的信息单独提取出来,然后按照语言把它们写在不同的文件中,中文信息写在中文文件中,英文信息写在英文文件中。
l 设置语言:当用户选择中文或者英文的时候,可以根据用户的选择进行设置。
l 调用资源文件:在完成功能的过程中,如果需要中文信息,从中文文件中读取,如果使用英文信息,从英文资源文件中读取。
l 系统中的数字、货币、日期也应该按照特定的方式进行处理。
在JSP的标准标签库中提供了多个标签,这些标签可以用于完成网站的国际化。
11.2 编写资源文件
在使用JSP提供的标准标签库中的国际化相关的标签的时候,对资源文件有一些要求。下面我们通过编写资源文件的过程来学习这些要求。
11.2.1 资源文件内容的确定
首先要提取网站中需要使用不同语言显示的信息,在用户管理界面中,包括如下信息:
l 页面提示信息
n 中文:所有用户信息。
n 英文:All User Info。
l 分页显示
n 中文:共有X页,这是第Y页。第一页 上一页 下一页 最后一页
n 英文:Total: X pages,current: Y . first previous next last
注:其中X和Y是变量。
l 表头信息
n 中文:用户编号、用户名、用户类型、生日、学历、地区、Email和地址。
n 英文:userid、username、type、birthday、degree、local、Email和address。
l 按钮信息
n 中文:删除和修改。
n 英文:delete和modify。
11.2.2 资源文件的格式
资源文件可以采用属性文件的形式也可以采用Java文件的形式。
采用属性文件
在属性文件中每一行表示一条信息。每一行的基本格式如下:
信息名=信息的值
信息名用于标识这条信息,在属性文件中不能有两条信息的名字是相同的,为了调用方便,在不同语言的属性文件中相同信息的名字是相同的。等号后面是这条信息的内容,在界面上显示的就是这个内容,中文文件中信息的内容是中文,英文中文中信息的内容是英文。例如,界面上的删除按钮上的文字在不同语言的属性文件中的实现如下:
中文:userinfo.delete=删除
英文:userinfo.delete=delete
注意:名字相同,都是userinfo.delete,值不相同,分别是“删除”和“delete”。
在信息中也可以使用变量,如果要在信息中使用变量,可以使用“{数字}”,如果有多个变量,可以使用多个不同的数字表示。例如,要显示当前用户,可以使用下面的格式:
pageinfo=共有 {0} 页,这是第 {1} 页。
该信息中就包含了两个变量,分别用“{0}”和“{1}”表示。在调用这个信息的时候会使用总页数和当前页数代替信息中的变量。
采用Java文件
使用Java文件,首先这个类必须继承java.util.ListResourceBundle。系统在读取资源文件的时候会使用这个类提供的一些方法。
对于资源文件中的信息的描述,采用静态的二维对象数组,也就是对象数组的数组,在文件中定义静态成员变量。下面是一个例子:
private static Object contents[][]=
{
{"userinfo.delete","delete"},
{"userinfo.modify","modify"},
{"pageinfo"," Total: {0} pages,current: {1} . "},
...
}
数组的每一个元素就是一条信息。每个元素又是一个数组,第一个元素是信息的名字,第二个元素是信息的值。如果信息中存在变量,用法与在属性文件中的用法相同。
除了定义这个成员变量之外,需要再定义一个获取该成员变量信息的方法,定义如下:
public Object [][] getContents()
{
return contents;
}
11.2.3 转换成Unicode编码
如果属性文件是中文,并且采用资源文件,需要转换成Unicode编码才可以,否则系统会出现乱码。可以使用JDK中的native2ascii命令进行转化,命令格式如下:
native2ascii 原文件 转换后文件
下面是一个转换的例子:
native2ascii userinfo.properties userinfo_zh.properties
resource.properties是原来的资源文件,resource_zh是转换后的文件,实际使用的是后面的文件。
11.2.4 资源文件的名字
首先是文件的扩展名,如果使用属性文件,文件的扩展名是properties。如果使用Java文件,使用编译后的Java文件。
不管使用Java文件还是使用属性文件,文件都由两部分组成:第一部分是文件的名字,通常根据作用命名;第二部分是文件的语言类型,需要根据所使用的语言确定,这个采用国际标准,也可能遇到要区分使用同一种语言的多个国家,在文件的后面需要增加国家代码。
下面是一个资源文件的名字,采用属性文件的方式:
resource_en.properties
其中,resource是资源文件的名字,en表示英语,中间使用下划线连接。
下面是采用Java文件的资源文件:
resource_en.java
其中,Resource是资源文件的名字,en表示语言,中间使用下划线连接。
下面的例子的资源文件名中包含了国家信息:
resource_es_MX.properties
表示采用西班牙语,国家为墨西哥。
如果文件名中不包括第二部分,也就是不包含国家和语言,这个文件就是默认资源文件,如果系统找不到相应的语言对应的资源文件,系统会使用默认资源文件。
如果想了解常用的语言和国家代码,可以通过浏览器的语言设置功能查看。要进行语言设置,选择【工具】à【Internet选项】,弹出一个设置界面,在该界面中选择【常规】à【语言】,弹出语言的查看和设置界面,点击【添加语言】弹出如图11.3所示界面,在该界面中可以看到所有的国家和语言。
11.3 浏览器中语言选择
11.2.5 资源文件的部署
资源文件的部署位置与类文件的部署位置相同,如果采用Java文件作为资源文件,该Java文件与普通的Java文件没有任何区别。如果使用属性文件,可以在classes中创建文件夹存放属性文件,并且可以创建多层文件夹。如果使用多层文件夹存放属性文件,在访问的时候需要写出文件夹的名字,就像访问类的时候,要写包的名字一样。
11.2.6 用户管理的资源文件
中文属性文件
文件名:userinfo.properties
文件内容如下:
title=所有用户信息
pageinfo=共有 {0} 页,这是第 {1} 页。
first=第一页
previous=上一页
next=下一页
last=最后一页
moveto.before=跳转到
moveto.after=页
moveto.confirm=确定
userinfo.userid=用户编号
userinfo.username=用户名
userinfo.type=用户类型
userinfo.birthday=生日
userinfo.degree=学历
userinfo.local=地区
userinfo.email=Email
userinfo.address=地址
userinfo.delete=删除
userinfo.modify=更新
usertype.commonuser=普通用户
usertype.manager=管理员
delete.confirm=删除该用户?
编码转换后的文件
转后的文件名:userinfo_zh.properties
文件内容如下:
title=/u6240/u6709/u7528/u6237/u4fe1/u606f
pageinfo=/u5171/u6709 {0} /u9875/uff0c/u8fd9/u662f/u7b2c {1} /u9875/u3002
first=/u7b2c/u4e00/u9875
previous=/u4e0a/u4e00/u9875
next=/u4e0b/u4e00/u9875
last=/u6700/u540e/u4e00/u9875
moveto.before=/u8df3/u8f6c/u5230
moveto.after=/u9875
moveto.confirm=/u786e/u5b9a
userinfo.userid=/u7528/u6237/u7f16/u53f7
userinfo.username=/u7528/u6237/u540d
userinfo.type=/u7528/u6237/u7c7b/u578b
userinfo.birthday=/u751f/u65e5
userinfo.degree=/u5b66/u5386
userinfo.local=/u5730/u533a
userinfo.email=Email
userinfo.address=/u5730/u5740
userinfo.delete=/u5220/u9664
userinfo.modify=/u66f4/u65b0
usertype.commonuser=/u666e/u901a/u7528/u6237
usertype.manager=/u7ba1/u7406/u5458
delete.confirm=/u5220/u9664/u8be5/u7528/u6237?
英文属性文件
文件名:userinfo_en.properties
文件内容如下:
title=All User Info
pageinfo=Total: {0} pages,current: {1} .
first=first
previous=previous
next=next
last=last
moveto.before=move to
moveto.after=
moveto.confirm=confirm
userinfo.userid=userid
userinfo.username=username
userinfo.type=type
userinfo.birthday=birthday
userinfo.degree=degree
userinfo.local=local
userinfo.email=Email
userinfo.address=address
userinfo.delete=delete
userinfo.modify=modify
usertype.commonuser=common
usertype.manager=manager
delete.confirm=Delete the selected user?
中文Java资源文件
文件名:userinfo_zh.java
文件内容如下:
package myresource;
import java.util.ListResourceBundle;
public class userinfo_zh extends ListResourceBundle
{
public Object [][] getContents()
{
return contents;
}
private static Object contents[][]=
{
{"title","所有用户信息"},
{"pageinfo","共有 {0} 页,这是第 {1} 页。"},
{"first","第一页"},
{"previous","上一页"},
{"next","下一页"},
{"last","最后一页"},
{"moveto.before","跳转到"},
{"moveto.after","页"},
{"moveto.confirm","确定"},
{"userinfo.userid","用户ID"},
{"userinfo.username","用户名"},
{"userinfo.type","用户类型"},
{"userinfo.birthday","生日"},
{"userinfo.degree","学历"},
{"userinfo.local","地区"},
{"userinfo.email","Email"},
{"userinfo.address","地址"},
{"userinfo.delete","删除"},
{"userinfo.modify","更新"},
{"usertype.commonuser","普通用户"},
{"usertype.manager","管理员"},
{"delete.confirm","删除该用户?"}
};
}
英文Java资源文件
文件名:userinfo_en.java
文件内容如下:
package myresource;
import java.util.ListResourceBundle;
public class userinfo_en extends ListResourceBundle
{
public Object [][] getContents()
{
return contents;
}
private static Object contents[][]=
{
{"title","All User Info"},
{"pageinfo","Total: {0} pages,current: {1} ."},
{"first","first"},
{"previous","previous"},
{"next","next"},
{"last","last"},
{"moveto.before","move to"},
{"moveto.after",""},
{"moveto.confirm","confirm"},
{"userinfo.userid","userid"},
{"userinfo.username","username"},
{"userinfo.type","type"},
{"userinfo.birthday","birthday"},
{"userinfo.degree","degree"},
{"userinfo.local","local"},
{"userinfo.email","Email"},
{"userinfo.address","address"},
{"userinfo.delete","delete"},
{"userinfo.modify","modify"},
{"usertype.commonuser","common"},
{"usertype.manager","manager"},
{"delete.confirm","Delete the selected user?"}
};
}
11.3 实现用户管理界面的国际化
用户管理界面的国际化需要完成如下功能:
u 设置语言
u 确定要访问的资源文件
u 访问资源文件中的内容
下面分别介绍。
11.3.1 设置所使用的语言
国际化使用的是标准标签库中的fmt标签库,要设置当前用户使用的语言可以使用该标签库中的<fmt:setLocale>标签。
该标签的格式如下:
<fmt:setLocale value= "语言国家代码" [scope= "{page|request|session|application}"]/>
value属性指出所使用的语言和国家,可以只有语言,如果同时有语言和国家,中间使用下划线连接。语言代码由ISO639标准定义,国家代码由ISO3166标准定义。例如使用英文可以使用en,使用中文可以使用zh,如果是中国大陆地区的中文可以使用zh_CN。
scope指出该设置的作用范围。通常情况下,该设置只对当前用户有效,也就是使用session,并且某个用户在整个访问过程中所使用的语言也应该是相同的。
要设置使用英文,可以使用下面的代码:
<fmt:setLocale value= "en"/>
如果当前用户希望使用简体中文,可以使用下面的代码:
<fmt:setLocale value= "zh_CN" scope= "session"/>
如果没有设置语言和地区,系统会采用用户请求时候使用的默认值。这个默认值与用户的浏览器设置相关,要设置浏览器的语言,可以参考11.2.4小节。
也可以为应用设置默认的地区和语言,通过web.xml文件设置,在web.xml文件中添加如下代码:
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.locale</param-name>
<param-value>en</param-value>
</context-param>
注:在有些网站中,网站会根据用户的IP地址,确定用户所处的地理位置,然后为用户选择一个默认语言。
11.3.2 确定要访问的资源文件
Web应用中可能存在多个资源文件,在使用的时候需要确定使用哪一个资源文件。可以使用<fmt:setBundle>标签来确定使用哪个资源文件。
<fmt:setBundle>标签的基本格式如下:
<fmt:setBundle [var="变量名"]
[scope="{page|request|session|application}"]
basename="资源文件的名字"/>
var属性和scope属性与前面介绍的其他标签中var属性和scope属性的作用是相同的。basename指出要使用的资源文件的名字,必须是完整的名字。如果是Java文件应该包含包的信息,如果是属性文件,应该包含属性文件所在文件夹的信息。另外,在文件中不需要写出文件的后缀名以及资源文件的文件名中标识国家和语言的部分。
例如,要使用前面编写好的资源文件,可以使用下面的代码:
<fmt:setBundle var="userinfo_re"
basename="myresource.userinfo"/>
这个标签的作用是把basename属性指出的资源文件中的信息保存到var指定的变量userinfo中。注意basename中的格式,myresource是存放资源文件的文件夹,userinfo是资源文件的名字,不包含后缀名properties,也不包含_en或者_zh等信息。
在使用这个标签的时候,如果不使用var指定一个变量,则这个资源文件将成为默认的资源文件,如果在访问资源文件中的内容的时候,不指定资源文件就会访问这个默认的资源文件。
<fmt:setBundle>的作用是先确定资源文件,然后通过其他标签来使用。也可以采用另外一种方式,在使用资源文件的时候确定资源文件,这时可以使用<fmt:bundle>标签。
<fmt:bundle>标签的格式如下:
<fmt:bundle basename="资源文件的名字" [prefix="前缀"]>
<fmt:message>标签
</fmt:bundle>
该标签的属性主要是basename,作用与<fmt:setBundle>标签中的basename属性的作用完全相同。标签中的<fmt:message>标签用于读取资源文件中的信息,接下来会介绍。
也可以使用prefix属性指出资源文件中的多条消息的相同部分。例如,资源文件中的userinfo.delete和userinfo.modify,他们具有相同的前缀“userinfo.”。为了访问方便,可以在使用<fmt:bundle>标签的时候指出这个前缀,这样在访问这两条消息的时候,就可以直接写delete和modify,而不用写userinfo.delete和userinfo.modify了。
11.3.3 访问资源文件中的内容
访问资源文件可以使用<fmt:message>标签。该标签的基本格式如下:
<fmt:message key="消息名"
[bundle="bundle名字"]
[var="变量名"]
[scope="{page|request|session|application}"]
/>
标签的基本作用是在界面上显示资源文件中的信息。
该信息从哪个资源文件中读取,可以通过bundle属性确定,bundle属性确定的值是在前面通过<fmt:setBundle>设置好的。如果该标签出现在<fmt:bundle>标签内部,<ftm:message>标签不再需要bundle属性。
要访问资源文件中的哪条信息,由key属性确定。如果<fmt:bundle>标签使用prerfix属性指定了前缀,则实际的消息名字是prefix指定的前缀加上key属性指定的名字。
该标签的默认作用是输出,如果该标签使用了var属性,则消息会存储在var属性指定的变量中,而不是显示在界面上。也可以使用scope属性指定变量的作用范围。
下面的三段代码的作用相同。
代码段1:
<!--设置资源文件-->
<fmt:setBundle var="userinfo_re"
basename="myresource.userinfo"/>
<!--访问资源文件-->
<fmt:message key="userinfo.delete"
bundle="userinfo_re"
/>
代码段2:
<!--在使用资源文件的同时,设置资源文件-->
<fmt:bundle basename="myresource.userinfo">
<!--访问资源文件-->
<fmt:message key="userinfo.delete"/>
</fmt:bundle>
代码段3:
<!--在使用资源文件的同时,设置资源文件-->
<fmt:bundle basename="myresource.userinfo" prefix="userinfo.">
<!--访问资源文件-->
<fmt:message key="delete"/>
</fmt:bundle>
如果想把资源文件中的信息存储在变量中,可以使用下面的代码:
<fmt:bundle basename="myresource.userinfo" prefix="userinfo.">
<!--访问资源文件-->
<fmt:message key="delete"
var="delete"
/>
</fmt:bundle>
如果要访问的消息中包含变量则需要提供变量的值,可以使用<fmt:param>标签完成。
<fmt:param>标签的基本格式如下:
<fmt:param value="参数的值"/>
或者
<fmt:param>
参数的值
</fmt:param>
如果在消息中使用了多个参数,则需要使用多个<fmt:param>标签,参数的顺序与消息中的变量的顺序应该保持一致。
前面编写的资源文件中的用户信息中包含了变量,要访问这个信息可以使用下面的代码:
<!--在使用资源文件的同时,设置资源文件-->
<fmt:bundle basename="myresource.userinfo">
<!--访问资源文件-->
<fmt:message key="pageinfo">
<!--传递第一个参数:总页数-->
<fmt:param value="${pageCount}"/>
<!--传递第二个参数:当前页数-->
<fmt:param value="${pageNo}"/>
</fmt:message>
</fmt:bundle>
11.3.4 添加语言选择功能
在界面上添加两个超链接,内容分别是“中文”和“English”。然后添加处理文件,当用户点击某一个超链接的时候应该把用户的选择设置成当前用户使用的语言。
超链接如下:
<a href="findAllUser?language=zh">中文</a>|
<a href="findAllUser?language=en">English</a>
处理代码要获取用户的选项,然后使用<fmt:setLocale>标签赋值。代码如下:
<c:if test="${!empty param.language}">
<fmt:setLocale value="${param.language}" scope="session" />
</c:if>
先判断有没有用户选择,如果没有的话就不需要设置了,采用默认值,如果有,则根据用户的选择进行设置。
11.3.5 修改后的文件
文件名:userlist.jsp
源代码:
<%@ page contentType="text/html;charset=gb2312"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<c:if test="${!empty param.language}">
<fmt:setLocale value="${param.language}" scope="session"/>
</c:if>
<script language="javascript">
function init(){
alert("${info}");
}
<c:if test="${!empty info}">
window.onload=init;
</c:if>
</script>
<fmt:bundle basename="myresource.userinfo">
<h2 align=center>
<fmt:message key="title"/>
<h2>
<font size=2>
<a href="findAllUser?language=zh">中文</a>|
<a href="findAllUser?language=en">English</a>
</font><br>
<font size=4>
<fmt:message key="pageinfo">
<fmt:param value="${pageCount}"/>
<fmt:param value="${pageNo}"/>
</fmt:message>
<!--如果是第一页,则不显示超链接-->
<c:if test="${pageNo==1}">
<fmt:message key="first"/>
<fmt:message key="previous"/>
</c:if>
<!--如果不是第一页,则显示超链接-->
<c:if test="${pageNo!=1}">
<a href="findAllUser?pageNo=1"><fmt:message key="first"/></a>
<a href="findAllUser?pageNo=${pageNo-1}"><fmt:message key="previous"/></a>
</c:if>
<!--如果是最后一页,则不显示超链接-->
<c:if test="${pageNo==pageCount}">
<fmt:message key="next"/>
<fmt:message key="last"/>
</c:if>
<!--如果不是第一页,则显示超链接-->
<c:if test="${pageNo!=pageCount}">
<a href="findAllUser?pageNo=${pageNo+1}"><fmt:message key="next"/></a>
<a href="findAllUser?pageNo=${pageCount}"><fmt:message key="last"/></a>
</c:if>
<form action="findAllUser">
<fmt:message key="moveto.before"/>
<input type="text" name="pageNo">
<fmt:message key="moveto.after"/>
<input type="submit" value="<fmt:message key="moveto.confirm"/>">
</form>
</font>
<table align=center>
<tr>
<th><fmt:message key="userinfo.userid"/></th>
<th><fmt:message key="userinfo.username"/></th>
<th><fmt:message key="userinfo.type"/></th>
<th><fmt:message key="userinfo.birthday"/></th>
<th><fmt:message key="userinfo.degree"/></th>
<th><fmt:message key="userinfo.local"/></th>
<th><fmt:message key="userinfo.email"/></th>
<th><fmt:message key="userinfo.address"/></th>
<th><fmt:message key="userinfo.delete"/></th>
<th><fmt:message key="userinfo.modify"/></th>
</tr>
<c:forEach items="${userlist}" var="user" >
<tr>
<td>${user.userid}</td>
<td>${user.username}</td>
<td>
<c:if test="${user.type==0}">
<fmt:message key="usertype.commonuser"/></c:if>
<c:if test="${user.type==1}">
<fmt:message key="usertype.manager"/></c:if>
</td>
<td>${user.birthday}</td>
<td>${user.degree}</td>
<td>${user.local}</td>
<td>${user.email}</td>
<td>${user.address}</td>
<td>
<form action="updateFindUser" method="post">
<input type="submit" value="<fmt:message key="userinfo.modify"/>">
<input type="hidden" name="userid" value="${user.userid}">
</form>
</td>
<td>
<form action="deleteUser" method="post"
onSubmit="return confirm('<fmt:message key="delete.confirm"/>');">
<input type="hidden" name="userid" value="${user.userid}">
<input type="submit" value="<fmt:message key="userinfo.delete"/>">
</form>
</td>
</tr>
</c:forEach>
</table>
</fmt:bundle>
11.4 数字的格式化
在很多应用中需要根据特定的格式输出数字,例如在财务应用中,需要把数字按照3位一组然后用逗号分隔。对于这些需求,在输出数字的时候就需要对数字进行格式化。
11.4.1 格式化数字
数字的格式化使用标准标签库中的格式化标签中的<fmt:formatNumber>标签完成。基本格式如下:
<fmt:formatNumber value="目标数字"
[type="{number|currency|percent"]
[pattern="格式"]
[currencySymbol="货币符号"]
[groupingUsed="{true|false}"]
[maxIntegerDigits="最大整数位"]
[minIntegerDigits="最小整数位"]
[maxFractionDigits="最大小数位"]
[minFractionDigits="最小小数位"]
[var="变量名"]
[scope="{page|request|session|application}"]
/>
value属性指出需要格式化的数字。type指出数字的类型,可选的类型是数字、货币和百分数。pattern属性可以让用户采用自定义的格式来设计数字的显示方式。currencySymbol用于指定货币的符号,在格式化货币的时候起作用。如果不指定这个值,系统会根据默认的Local(国家和语言)确定货币符号。maxIntegerDigits、minIntegerDigits、maxFractionDigits和minFractionDigits分别表示小数点之前的最大位数、小数点之前的最小位数、小数点之后的最大位数和小数点之后的最小位数。var属性可以指定一个变量保存格式化后的结果,如果没有var属性,格式化后的结果将直接显示。scope指出变量的作用范围。
例,下面的代码:
<fmt:formatNumber value="456.7"
maxIntegerDigits="7"
minIntegerDigits="4"
maxFractionDigits="3"
minFractionDigits="2"
/>
输出的结果是:0,456.70
因为整数部分和小数部分都小于最小位数,所以都补0。
如果把456.7替换成123123456.78911,输出的结果是:3,123,456.789。
因为整数部分和小数部分都大于最大位数,所以多出部分都被舍弃了。
11.4.2 转换数字
前面介绍的<fmt:format>标签的作用是把一个数字或者货币按照一定的格式显示,主要用于输出。有时候,需要把用户输入的信息转换成数字,而用户可能是按照某种特定的格式输入的。把输入信息转换成数字,可以使用<fmt:parseNumber>标签。该标签的基本格式如下:
<fmt:parseNumber value="格式化字符串"
[type="{number|currency|percent}"]
[pattern="格式"]
[parseLocale="parseLocale"]
[integerOnly="{true|false}"]
[var="变量名"]
[scope="{page|request|session|application}"]
/>
value属性指出需要转换成数字的格式化字符串。type指出数字的类型,可选的类型是数字、货币和百分数,默认是数字。pattern属性指出字符串的格式。integerOnly属性指定是否仅仅解析给定值的整数部分。parseLocale指出转换所使用的Locale。var属性可以指定一个变量保存转换后的结果,如果没有var属性,转换后的结果将直接显示。scope指出变量的作用范围。
11.5日期的格式化
11.5.1 格式化日期
在很多应用中都需要根据特定的格式输出日期,在标准标签库的格式化标签库中提供了<fmt:formatDate>标签用于完成日期的格式化。该标签的基本格式如下:
<fmt:formatDate
value="要格式化的日期"
[type="{time|date|both}"]
[dateStyle="{default|short|medium|long|full}"]
[timeStyle="{default|short|medium|long|full}"]
[pattern="自定义模式"]
[timeZone="时区"]
[var="变量名"]
[scope="{page|request|session|application}"]
/>
value属性指出要格式化的日期。type属性支持格式化类型:时间、日期或者全部。
dateStyle指出日期的格式,每种格式对应的形式如表11.1所示:
表11.1 日期格式
default 2007-5-4
short 07-5-4
medium 2007-5-4
long 2007年5月4日
full 2007年5月4日 星期五
timeStyle指出时间的格式,每种格式对应的形式如表11.2所示:
表11.2 时间格式
default 16:27:16
short 下午4:27
medium 16:27:16
long 下午04时27分16秒
full 下午04时27分16秒 CST
pattern用于确定自定义格式,可以使用表11.3所示的模式符。
表11.3 模式字符
字符 描述
G 公元(A.D. 或者B.C.)
y 年(yy为两位的年,yyyyy表示4位的年)
M 月(MM为数字,MMM为英文缩写)
w 周(按年计算,ww为两位数字)
W 周(按月计算)
D 按年计算的日
d 按月计算的日
F 周内数字表示的天
E 周内文字表示的天
a 表示上午或者下午(AM 或者 PM)
H 时
h 时
K 时
k 时
m 分
s 秒
S 毫秒
z 完全时区名
Z 时区编号
timeZone属性指出时区。var指定的变量用于保存格式化后的日期,如果没有指定var属性,则直接显示格式化后的结果。scope指定变量的作用范围。
11.5.2 转化日期
上面介绍的是把日期按照特定的格式转换成字符串输入。有的时候需要把用户输入的字符串转换成日期,这时候需要按照特定的格式转换,可以使用<fmt:parseDate>标签进行转换。该标签的基本格式如下:
<fmt:parseDate
value="日期字符串"
[type={time|date|both}]
[dateStyle="{default|short|medium|long|full}"]
[timeStyle="{default|short|medium|long|full}"]
[pattern="自定义模式"]
[timeZone="时区"]
[parseLocale="parseLocale"]
[var="变量名"]
[scope="{page|request|session|application}"]
/>
各个属性的含义与前面介绍的<fmt:formatDate>中的属性的含义基本相同。
小结
要使Java Web应用支持国际化,需要完成以下步骤:
u 编写资源文件:把网站中需要使用不同语言显示的信息单独提取出来,然后按照语言把它们写在不同的文件中,中文信息写在中文文件中,英文信息写在英文文件中。资源文件可以使用属性文件的形式,也可以采用Java文件的形式,不管采用什么形式,都需要按照一定的规则对文件命名。
u 设置语言:当用户选择中文或者英文的时候,可以根据用户的选择进行设置。通常需要在网站中提供这样的功能,或者系统根据用户使用的语言来确定语言,或者根据用户IP地址所在的位置来确定语言。
u 调用资源文件:在显示信息的过程中,如果需要中文信息,从中文文件中读取,如果使用英文信息,从英文资源文件中读取。
u 系统中的数字、货币、日期也应该按照特定的方式进行处理。
JSP培训目录:
JSP培训(1)——概述 |
JSP培训(2)——运行原理、文档结构、简单输入输出 |
JSP培训(3)——客户端验证、常用输出方式、JSTL基本用法 |
JSP培训(4)——实例:登录功能、jsp:forward标签、jsp:include标签、include指令、EL、c:if |
JSP培训(5)——使用JavaBean完成业务逻辑 |
JSP培训(6)——使用Servlet作为控制器实现MVC模式 |
JSP培训(7)——使用JDBC完成动态验证、采用MVC完成数据查询 |
JSP培训(8)——添加功能和分页显示 |
JSP培训(9)——使用MVC模式完成删除和修改功能 |
JSP培训(10)——使用JavaBean封装对数据库的访问、连接池的配置和使用 |
JSP培训(11)——Java Web中的安全控制 |
JSP培训(12)——Java Web应用国际化 |
JSP培训(13)——异常处理 |
JSP培训(14)——购物车实例(上) |
JSP培训(15)——购物车实例(下)及小结 |