EL表达式 JSTL中的常用EL函数 动态数据的国际化

时间:2023-12-04 19:54:20

ELppt:

EL 全名为Expression Language。EL主要作用:

获取数据:

•EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(某个web域中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组)

执行运算:

•利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。${user==null}

获取web开发常用对象

•EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。

调用Java方法

•EL表达式允许用户开发自定义EL函数,以在JSP页面中通过EL表达式调用Java类的方法。

获取数据

使用EL表达式获取数据语法:“${标识符}”

EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。 示例:${user}

EL表达式也可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据,例如:

•${user.address.city}

•${user.likes[0]}:访问有序集合某个位置的元素

•${map[‘key’]} :获得map集合中指定key的值

结合JSTL的foreach标签,使用EL表达式也可以很轻松迭代各种类型的数组或集合,示例:

•迭代数组

•迭代collection类型集合(set/list)

•迭代map类型集合

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="cn.itcast.web.jsp.el.*" %>
<%@ page import="java.util.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<c:set var="username" value="jack" scope="page"/>
用户名:${username}
<hr/>
<jsp:useBean id="user" class="cn.itcast.web.jsp.el.User" scope="page"/>
<c:set target="${user}" property="username" value="marry"/>
<c:set target="${user}" property="age" value="22"/>
用户名:${user.username}
年龄:${user.age}
<hr/>
<%
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
request.setAttribute("LIST",list);
%>
集合中第二个元素:${LIST[1]}
<hr/>
<jsp:useBean id="map" class="java.util.LinkedHashMap" scope="page"/>
<c:set target="${map}" property="key" value="one"/>
<c:set target="${map}" property="value" value="jack"/>
第一个元素的key值:${map.key}
第一个元素的value值:${map.value}
<hr/>
<%
int[] intArray = {10,20,30};
pageContext.setAttribute("intArray",intArray);
%>
数组第一个元素值为:${intArray[2]}<br/>
<hr/>
找不到时,返回:${mapp}
</body>
</html>

执行运算

语法:${运算表达式},EL表达式支持如下运算符:

EL表达式 JSTL中的常用EL函数 动态数据的国际化

empty运算符:检查变量是否为null或“空”,很好用!!!

二元表达式:${user!=null?user.name : “”} ,很好用!!!

[ ] 和 . 号运算符

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
10+3=${10+3}<br/>
10-3=${10-3}<br/>
10*3=${10*3}<br/>
10/3=${10/3}<br/>
<hr/>
10>3=${10>3}<br/>
10>=3=${10>=3}<br/><=${10<=3}<br/><=3=${10<=3}<br/>
10==3=${10==3}<br/>
10!=3=${10!=3}<br/>
<hr/>
true&&false=${true && false}<br/>
true&&true=${true && true}<br/>
false&&false=${false && false}<br/>
<hr/>
true||false=${true || false}<br/>
true||true=${true || true}<br/>
false||false=${false || false}<br/>
<hr/>
!false=${!false}<br/>
!true=${!true}<br/>
<hr/>
<c:set var="username" value="杰克" scope="session"/>
<c:remove var="username" scope="session"/>
<%--
session.invalidate();
--%>
欢迎${!empty username?username:'游客'}光临 Web应用名:<%=request.getContextPath()%>
<hr/>
Web应用名:${pageContext.request.contextPath} <form action="/day17"></form> </body>
</html>

获得web开发常用对象

EL表达式语言中定义了11个隐含对象,使用这些隐含对象可以很方便地获取web开发中的一些常见对象,并读取这些对象的数据。

语法:${隐式对象名称} :获得对象的引用

隐含对象名称

描 述

pageContext

对应于JSP页面中的pageContext对象(注意:取的是pageContext对象。)

pageScope

代表page域中用于保存属性的Map对象

requestScope

代表request域中用于保存属性的Map对象

sessionScope

代表session域中用于保存属性的Map对象

applicationScope

代表application域中用于保存属性的Map对象

param

表示一个保存了所有请求参数的Map对象

paramValues

表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[],从0开始

${paramValues.like[0]}

header

表示一个保存了所有http请求头字段的Map对象

headerValues

同上,返回string[]数组。注意:如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”]

cookie

表示一个保存了所有cookie的Map对象

initParam

表示一个保存了所有web应用初始化参数的map对象

测试各个隐式对象

注意事项

•测试headerValues时,如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”]

•测试cookie时,例${cookie.key}取的是cookie对象,如访问cookie的名称和值,须${cookie.username.name}或${cookie.username.value}

•new Cookie(“username”,”jack”);

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<c:set var="username" value="jack" scope="page"/>
<c:set var="username" value="marry" scope="request"/>
用户名:${pageScope.username}
<hr/>
<a href="${pageContext.request.contextPath}/result.jsp?name=berry&pass=123&like=sing&like=dance&like=read">
单击
</a>
<hr/>
WebName=${initParam.webName}<br/>
WebAuthor=${initParam.webAuthor}<br/>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Web初始化参数 -->
<context-param>
<param-name>webName</param-name>
<param-value>day17</param-value>
</context-param>
<context-param>
<param-name>webAuthor</param-name>
<param-value>赵君</param-value>
</context-param> </web-app>
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
用户名:${param.name}<br/>
密码:${param.pass}<br/>
爱好A:${paramValues.like[0]}
爱好B:${paramValues.like[1]}
爱好C:${paramValues.like[2]}
<hr/>
浏览器相关信息${header['User-Agent']}<br/>
字符编码${headerValues['Accept-Encoding'][0]}
<br/>
<%--
Cookie cookie = new Cookie("username","jack");
cookie.setMaxAge(5*60);
response.addCookie(cookie);
--%>
Cookie的名:${cookie.username.name}<br/>
Cookie的值:${cookie.username.value}<br/>
</body>
</html>

使用EL调用Java方法

EL表达式语法允许开发人员开发自定义函数,以调用Java类的方法。

•示例:${prefix:method(params)}

•在EL表达式中调用的只能是Java类的静态方法。

•这个Java类的静态方法需要在TLD文件中描述,才可以被EL表达式调用。

•EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通Java程序代码所能完成的功能。

•EL函数只能访问与WEB无关的需求,与WEB有关的需求还是需要使用自定义标签来解决。

EL Function开发步骤

一般来说, EL自定义函数开发与应用包括以下三个步骤:

•编写一个Java类的静态方法。

•编写标签库描述符(tld)文件,在tld文件中描述自定义函数,在WEB-INF/目录下。

•在JSP页面中导入和使用自定义函数。

示例:开发对html标签进行转义的el function

•${el:filter('<a href=“#">点点</a>')}

注意事项:

编写完标签库描述文件后,需要将它放置到<web应用>\WEB-INF目录中或WEB-INF目录下的除了classes和lib目录之外的任意子目录中。

TLD文件中的<uri> 元素用指定该TLD文件的URI,在JSP文件中需要通过这个URI来引入该标签库描述文件。

<function>元素用于描述一个EL自定义函数,其中:

•<name>子元素用于指定EL自定义函数的名称。

•<function-class>子元素用于指定完整的Java类名。

•<function-signature>子元素用于指定Java类中的静态方法的签名,方法签名必须指明方法的返回值类型及各个参数的完整类型,各个参数之间用逗号分隔。

EL表达式是JSP 2.0规范中的一门技术。因此,若想正确解析EL表达式,需使用支持Servlet2.4/JSP2.0技术的WEB服务器。

注意:有些Tomcat服务器如不能使用EL表达式

(1)升级成tomcat6/7

(2)升级JSTL的JAR包

(3)在JSP中加入<%@ page isELIgnored="false" %>即,告诉JSP引擎不忽略EL表达式语言。

JSTL中的常用EL函数

由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用。

这些EL函数在JSTL开发包中进行描述,因此在JSP页面中使用SUN公司的EL函数库,需要导入JSTL开发包,并在页面中导入EL函数库,如下所示:

•在页面中使用JSTL定义的EL函数:%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%导入standard.jar和jstl.jar

fn:toLowerCase

fn:toLowerCase函数将一个字符串中包含的所有字符转换为小写形式,并返回转换后的字符串,它接收一个字符串类型的参数,例如

•fn:toLowerCase("Www.IT315.org") 的返回值为字符串“www.it315.org”

•fn:toLowerCase("")的返回值为空字符串

  fn:toUpperCase

fn:toUpperCase函数将一个字符串中包含的所有字符转换为大写形式,并返回转换后的字符串,它接收一个字符串类型的参数。例如:

•fn:toUpperCase("Www.IT315.org") 的返回值为字符串“WWW.IT315.ORG”

•fn:toUpperCase(“”)的返回值为空字符串

  fn:trim

fn:trim函数删除一个字符串的首尾的空格,并返回删除空格后的结果字符串,它接收一个字符串类型的参数。需要注意的是,fn:trim函数不能删除字符串中间位置的空格。

•例如,fn:trim(" www.it315.org ") 的返回值为字符串“www.it 315.org”。

fn:length

fn:length函数返回一个集合或数组大小,或返回一个字符串中包含的字符的个数,返回值为int类型。fn:length函数接收一个参数,这个参数可以是<c:forEach>标签的items属性支持的任何类型,包括任意类型的数组、java.util.Collection、java.util.Iterator、java.util.Enumeration、java.util.Map等类的实例对象和字符串。

如果fn:length函数的参数为null或者是元素个数为0的集合或数组对象,则函数返回0;如果参数是空字符串,则函数返回0。

    fn:split

•fn:split函数以指定字符串作为分隔符,将一个字符串分割成字符串数组并返回这个字符串数组。

•fn:split函数接收两个字符串类型的参数,第一个参数表示要分割的字符串,第二个参数表示作为分隔符的字符串。

•例如,fn:split("www.it315.org", ".")[1]的返回值为字符串“it315”。

    fn:join

    fn:join函数以一个字符串作为分隔符,将一个字符串数组中的所有元素合并为一个字符串并返回合并后的结果字符串。fn:join函数接收两个参数,第一个参数是要操作的字符串数组,第二个参数是作为分隔符的字符串。

    如果fn:join函数的第二个参数是空字符串,则fn:join函数的返回值直接将元素连接起来。例如:

    •假设stringArray是保存在Web域中的一个属性,它表示一个值为{"www","it315","org"}的字符串数组,则fn:join(stringArray, “.")返回字符串“www.it315.org”

    •fn:join(fn:split("www,it315,org", ","), ".") 的返回值为字符串“www.it315.org”

    fn:indexOf

    fn:indexOf函数返回指定字符串在一个字符串中第一次出现的索引值,返回值为int类型。fn:indexOf函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,那么,不管第二个参数字符串在第一个参数字符串中出现几次,fn:indexOf函数总是返回第一次出现的索引值;如果第一个参数中不包含第二个参数,则fn:indexOf函数返回-1。如果第二个参数为空字符串,则fn:indexOf函数总是返回0。例如:

    fn:indexOf("www.it315.org","t3") 的返回值为5

    fn:contains

    fn:contains函数检测一个字符串中是否包含指定的字符串,返回值为布尔类型。fn:contains函数在比较两个字符串是否相等时是大小写敏感的。

    fn:contains函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,则fn:contains函数返回true,否则返回false。如果第二个参数的值为空字符串,则fn:contains函数总是返回true。实际上,fn:contains(string, substring)等价于fn:indexOf(string, substring) != -1。

    忽略大小的EL函数:fn:containsIgnoreCase

    fn:startsWith

    fn:startsWith函数用于检测一个字符串是否是以指定字符串开始的,返回值为布尔类型。

    fn:startsWith函数接收两个字符串类型的参数,如果第一个参数字符串以第二个参数字符串开始,则函数返回true,否则函数返回false。如果第二个参数为空字符串,则fn:startsWith函数总是返回true。例如:

    fn:startsWith("www.it315.org","it315")的返回值为false

    与之对应的EL函数:fn:endsWith

    fn:replace

    fn:replace函数将一个字符串中包含的指定子字符串替换为其它的指定字符串,并返回替换后的结果字符串。fn:replace方法接收三个字符串类型的参数,第一个参数表示要操作的源字符串,第二个参数表示源字符串中要被替换的子字符串,第三个参数表示要被替换成的字符串。例如:

    fn:replace("www it315 org", " ", ".")的返回值为字符串“www.it315.org”

    fn:substring

    fn:substring函数用于截取一个字符串的子字符串并返回截取到的子字符串。fn:substring函数接收三个参数,第一个参数是用于指定要操作的源字符串,第二个参数是用于指定截取子字符串开始的索引值,第三个参数是用于指定截取子字符串结束的索引值,第二个参数和第三个参数都是int类型,其值都从0开始。例如:

    fn:substring("www.it315.org", 4, 9) 的返回值为字符串“it315”

    fn:substringAfter

    fn:substringAfter函数用于截取并返回一个字符串中的指定子字符串第一次出现之后的子字符串。fn:substringAfter函数接收两个字符串类型的参数,第一个参数表示要操作的源字符串,第二个参数表示指定的子字符串,例如:

    fn:substringAfter(“www.it315.org”, “.”)的返回值为字符串“it315.org”。

    与之对应的EL函数为:fn:substringBefore

*2 EL的作用
  a)获取数据

普通变量/JavaBean/List/Set/Map,注意,一定要将其放置到域对象中

如果在域中找不到对应的值,返回空白字符串,不是NULL

b)执行运算

    算术/关系/逻辑

有用的二个运算:empty和**?**:**(二元运算符)

c)获取web开发常用对象(11个隐式对象)

d)调用Java方法,即EL自定义函数

EL是对标签(自定义和JSTL标签)补充和简化

3 EL的11个内置对象

*pageContext,例如:${pageContext.request.contextPath}

*pageScope/requestScope/sessionScope/applicationScope

*param/paramValues(数组)

header/headerValues(数组)

cookie/initParam

4 EL自定义函数和自定义标签有何不同?适合于什么样的场景?

函数:

适合于与非Web相关的应用,例如字符串相关的处理   
    相关函数的开发过程

1 写一个EL函数类,该类无需继承和实现任何类或接口

//${el:filter("")}//普通类
public class Filter {
//EL自定义函数
public static String filter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("&lt;");
break;
case '>':
result.append("&gt;");
break;
case '&':
result.append("&amp;");
break;
case '"':
result.append("&quot;");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
}

2 在WEB-INF/*.tld文件,描述自定义函数和对应处理类的关系

<?xml version="1.0" encoding="UTF-8" ?>
<taglib 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-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>el</short-name>
<uri>http://java.sun.com/jsp/jstl/el</uri>
<function>
<name>filter</name>(函数名)
<function-class>cn.itcast.web.jsp.el.Filter</function-class>(函数处理类的完整路径)
<function-signature>java.lang.String filter(java.lang.String)</function-signature>(函数方法签名)
</function>
</taglib>

3 在需要使用的jsp文件中,能过<%@taglib%>指令引入对应的EL函数

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/el" prefix="el" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
${el:filter('<script type="text/javascript"> </script>')}<br/>
</body>
</html>

标签:
    适合于与Web相关的应用,因为标签中有pageContext对象

6 国际化

d:\>native2ascii -encoding gb2312 a.txt message_zh_CN.properties(输出的目标文件)

软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。

国际化又称为 i18n:internationalization

软件实现国际化,需具备哪些特征:

•对于程序中固定使用的文本元素,例如菜单栏、导航条等中使用的文本元素、或错误提示信息,状态信息等,需要根据来访者的地区和国家,选择不同语言的文本为之服务。

•对于程序动态产生的数据,例如(日期,货币等),软件应能根据当前所在的国家或地区的文化习惯进行显示。

固定文本元素的国际化

对于软件中的菜单栏、导航条、错误提示信息,状态信息等这些固定不变的文本信息,可以把它们写在一个properties文件中,并根据不同的国家编写不同的properties文件。这一组properties文件称之为一个资源包。

在JavaAPI中提供了一个ResourceBundle 类用于描述一个资源包,并且 ResourceBundle类提供了相应的方法getBundle,这个方法可以根据来访者的国家地区自动获取与之对应的资源文件予以显示。

创建资源包和资源文件

一个资源包中的每个资源文件都必须拥有共同的基名。除了基名,每个资源文件的名称中还必须有标识其本地信息的附加部分。例如:一个资源包的基名是“myproperties”,则与中文、英文环境相对应的资源文件名则为:

•“myproperites_zh.properties” “myproperites_en.properties”

每个资源包都应有一个默认资源文件,这个文件不带有标识本地信息的附加部分。若ResourceBundle对象在资源包中找不到与用户匹配的资源文件,它将选择该资源包中与用户最相近的资源文件,如果再找不到,则使用默认资源文件。例如:

•myproperites.properties

资源文件的书写格式

资源文件的内容通常采用“关键字=值”的形式,软件根据关键字检索值显示在页面上。一个资源包中的所有资源文件的关键字必须相同,值则为相应国家的文字。

并且资源文件中采用的是properties格式文件,所以文件中的所有字符都必须是ASCII字码,对于像中文这样的非ACSII字符,须先进行编码。(java提供了一个native2ascII命令用于编码)。例:

属性文件是不能保存中文的

username=username

password=password

submit=submit

resource_en.properties文件

username=\u7528\u6237\u540d

password=\u5bc6\u7801

submit=\u63d0\u4ea4

resource_zh.properties文件

编程实现固定文本的国际化

ResourceBundle类提供了一个静态方法getBundle,该方法用于装载资源文件,并创建ResourceBundle实例:

Locale currentLocale = Locale.getDefault();

ResourceBundle myResources = ResourceBundle.getBundle(basename, currentLocale);

•basename为资源包基名(且必须为完整路径)。

•如果与该locale对象匹配的资源包子类找不到。一般情况下,则选用默认资源文件予以显示。

加载资源文件后,程序就可以调用ResourceBundle 实例对象的 getString 方法获取指定的资源信息名称所对应的值。

String value = myResources.getString(“key");

开发步骤:

            a)写一个本地化的jsp页面

b)再将本地化的jsp页面中的内容提出到资源包中,即*.properties文件

c)通过ResourceBundle加载资源包

注意:在Web页面中,如果请求中找不到对应的Locale,即访问缺省的资源包 
            非Web页面中,如果请求中找不到对应的Locale,即与操作系统对应的资源包

package cn.itcast.web.jsp.i18n;

import java.util.Locale;
import java.util.ResourceBundle; //使用JavaAPI操作国际化资源
public class TestI18N {
public static void main(String[] args) {
//绑定对应的资源文件
ResourceBundle rb =
ResourceBundle.getBundle(
"cn/itcast/web/jsp/config/message",Locale.CHINA);
//从资源文件中取得对应的信息
String value = rb.getString("hello");
//显示国际化结果
System.out.println("value="+value);
}
}
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<%
ResourceBundle rb =
ResourceBundle.getBundle(
"cn/itcast/web/jsp/config/message",request.getLocale());
%>
<body>
<table border="1" align="center">
<caption><%=rb.getString("login.title")%></caption>
<tr>
<th><%=rb.getString("login.username")%></th>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<th><%=rb.getString("login.password")%></th>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value='<%=rb.getString("login.submit")%>'/>
</td>
</tr>
</table>
</body>
</html>

在WEB应用中实现国际化

    国际化标签

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<fmt:setLocale value=“${pageContext.request.locale}”/>(页面的Locale)

<fmt:setBundle basename=“cn/itcast/web/jsp/config/hello”/>(资源文件基名)

<fmt:message key=“itcast.hello”>(资源文件key)

<fmt:param value=“itcast.name”/>(资源文件占位符)

设置POST请求消息的字符集编码 <fmt:requestEncoding value="UTF-8"/>

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<fmt:setLocale value="${pageContext.request.locale}"/>
<fmt:setBundle basename="cn/itcast/web/jsp/config/message"/>
<body>
<table border="1" align="center">
<caption>
<fmt:message key="login.title"/>
</caption>
<tr>
<th><fmt:message key="login.username"/></th>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<th><fmt:message key="login.password"/></th>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value='<fmt:message key="login.submit"/>'/>
</td>
</tr>
</table>
<hr/>
<fmt:message key="hello">
<fmt:param value="jack"/>
<fmt:param value="marry"/>
</fmt:message>
</body>
</html>

动态数据的国际化

数值,货币,时间,日期等数据由于可能在程序运行时动态产生,所以无法像文字一样简单地将它们从应用程序中分离出来,而是需要特殊处理。Java 中提供了解决这些问题的 API 类(位于 java.util 包和 java.text 包中)

Locale 类

•Locale 实例对象代表一个特定的地理,政治、文化区域。

•一个 Locale 对象本身不会验证它代表的语言和国家地区信息是否正确,只是向本地敏感的类提供国家地区信息,与国际化相关的格式化和解析任务由本地敏感的类去完成。(若JDK中的某个类在运行时需要根据 Locale 对象来调整其功能,这个类就称为本地敏感类)

DateFormat类

DateFormat 类可以将一个日期/时间对象格式化为表示某个国家地区的日期/时间字符串,项目中不提倡用Date类型。

DateFormat 类除了可按国家地区格式化输出日期外,它还定义了一些用于描述日期/时间的显示模式的 int 型的常量,包括FULL, LONG, MEDIUM, DEFAULT, SHORT,实例化DateFormat对象时,可以使用这些常量,控制日期/时间的显示长度。

例如,对于日期/时间“2005年9月15日下午4时41分20秒”,如设置了DateFormat的显示模式,则日期/时间显示样式分别为:

•SHORT模式完全是数字的,在中文环境下显示为“05-9-15 下午4:41”;在英文环境下为“9/15/05 4:41 PM”。

•MEDIUM模式比SHORT模式长些,在中文环境显示为“2005-9-15 16:41:20”;在英文环境下显示为“Sep 15, 2005 4:41:20 PM”。

•LONG模式比MEDIUM模式更长一些,在中文环境下显示为“2005年9月15日下午04时41分20秒”;在英文环境下显示为“September 15, 2005 4:41:20 PM CST”。

•FULL模式指定日期/时间的完整格式,在中文环境下显示为“2005年9月15日星期四 下午04时41分20秒 CST”;在英文环境下,这个日期/时间显示为“Thursday, September 15, 2005 4:41:20 PM CST”。

实例化DateFormat类

实例化DateFormat类有九种方式,以下三种为带参形式,下面列出的三种方式也可以分别不带参,或只带显示样式的参数。

•getDateInstance(int style, Locale aLocale):以指定的日期显示模式和本地信息来获得DateFormat实例对象,该实例对象不处理时间值部分。

•getTimeInstance(int style, Locale aLocale):以指定的时间显示模式和本地信息来获得DateFormat实例对象,该实例对象不处理日期值部分。

•getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale):以单独指定的日期显示模式、时间显示模式和本地信息来获得DateFormat实例对象。

DateFormat 对象的方法:

•format: 将日期/时间对象格式化为符合某个本地环境习惯的字符串。

•parse:将符合某个本地环境习惯的日期/时间字符串解析为日期/时间对象

•注意:parse和format完全相反,一个是把date时间转化为相应地区和国家的显示样式,一个是把相应地区的时间日期转化成date对象,该方法在使用时,解析的时间或日期要符合指定的国家、地区格式,否则会抛异常。

•解析:2010年9月33日有异常吗?

DateFormat 对象通常不是线程安全的,每个线程都应该创建自己的 DateFormat实例对象

ThreadLocal<DateFormat>

package cn.itcast.web.jsp.i18n;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale; //演示DateFormat类的用法
public class Demo1 {
public static void main(String[] args) throws Exception {
//取得日期
//DateFormat df = DateFormat.getDateInstance(DateFormat.FULL,Locale.CHINA);
//取得日期和时间
//DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.US);
//String str = df.format(new Date());
//System.out.println(str); String str = "2011年11月33日 星期二";
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL,Locale.CHINA);
Date date = df.parse(str);
System.out.println(date.toLocaleString());
}
}
package cn.itcast.web.jsp.i18n;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale; //演示SimpleDateFormat的用法
public class Demo2 {
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.CHINA);
Date date = sdf.parse("2011-11-1");
Calendar c = Calendar.getInstance(Locale.CHINA);
c.setTime(date);
System.out.println(c.get(Calendar.YEAR)+"年");
System.out.println(c.get(Calendar.MONTH)+1+"月");
System.out.println(c.get(Calendar.DATE)+"日");
System.out.println(c.get(Calendar.DAY_OF_WEEK));//1(星期天)
System.out.println(c.get(Calendar.DAY_OF_MONTH));//
System.out.println(c.get(Calendar.DAY_OF_YEAR));//
}
}

国际化标签

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//创建时区(默认+08:00时区,即北京时区
TimeZone tz = TimeZone.getDefault();
pageContext.setAttribute("tz", tz);
%>
<jsp:useBean id="now" class="java.util.Date" scope="page" />
中国
<fmt:timeZone value="${tz}">
<fmt:formatDate
value="${now}"
type="both"
dateStyle="full"
timeStyle="full" />
</fmt:timeZone>
<hr />
美国
<fmt:timeZone value="GMT-08:00">
<fmt:formatDate
value="${now}"
type="both"
dateStyle="full"
timeStyle="full" />
</fmt:timeZone>
<hr />
开罗
<fmt:timeZone value="GMT+02:00">
<fmt:formatDate
value="${now}"
type="both"
dateStyle="full"
timeStyle="full" />
</fmt:timeZone>
<hr />
<fmt:formatDate
value="${now}"
pattern="yyyy-MM-dd-w-F-E hh:mm:ss"
timeZone="GMT-08:00" />
</body>
</html>

NumberFormat类

NumberFormat 可以将一个数值格式化为符合某个国家地区习惯的数值字符串,也可以将符合某个国家地区习惯的数值字符串解析为对应的数值

NumberFormat 类的方法:

•format 方法:将一个数值格式化为符合某个国家地区习惯的数值字符串

•parse 方法:将符合某个国家地区习惯的数值字符串解析为对应的数值。

实例化NumberFormat类时,可以使用locale对象作为参数,也可以不使用,下面列出的是使用参数的。

getNumberInstance(Locale locale):以参数locale对象所标识的本地信息来获得具有多种用途的NumberFormat实例对象

getIntegerInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理整数的NumberFormat实例对象

getCurrencyInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理货币的NumberFormat实例对象

getPercentInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理百分比数值的NumberFormat实例对象

package cn.itcast.web.jsp.i18n;

import java.text.NumberFormat;
import java.util.Locale; //演示NumberFormat的用法
public class Demo3 {
public static void main(String[] args) throws Exception { //Integer类型
//NumberFormat nf = NumberFormat.getIntegerInstance(Locale.CHINA);
//Long num = (Long) nf.parse("123");
//System.out.println("num="+num); //货币类型
//NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA);
//Long num = (Long) nf.parse("¥2011");
//System.out.println("num="+num); //百分比类型
NumberFormat nf = NumberFormat.getPercentInstance(Locale.CHINA);
Double num = (Double) nf.parse("50%");
System.out.println("num="+num); }
}

国际化标签

货币<fmt:formatNumber value="121212.35" type="currency"/><br/>

百分比<fmt:formatNumber value="121212.35" type="percent"/><br/>

自定义格式A<fmt:formatNumber value="121212.35" type="number" pattern=".0"/><br/>

自定义格式B<fmt:formatNumber value="121212.35" type="number" pattern="000,000.0"/><br/>

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
Integer类型:
<fmt:formatNumber value="315.123" type="number"/>
<hr/>
货币类型:
<fmt:formatNumber value="315.123" type="currency"/>
<hr/>
百分类型
<fmt:formatNumber value="315.123" type="percent"/>
<hr/>
</body>
</html>

MessageFormat

如果一个字符串中包含了多个与国际化相关的数据,可以使用MessageFormat类对这些数据进行批量处理。

例如:

At 12:30 pm on jul 3,1998, a hurricance destroyed houses and caused $1000000 of damage

•以上字符串中包含了时间、数字、货币等多个与国际化相关的数据,对于这种字符串,可以使用MessageFormat类对其国际化相关的数据进行批量处理。

MessageFormat 类如何进行批量处理呢?

•1.MessageFormat类允许开发人员用占位符替换掉字符串中的敏感数据(即国际化相关的数据)。

•2.MessageFormat类在格式化输出包含占位符的文本时,messageFormat类可以接收一个参数数组,以替换文本中的每一个占位符。

模式字符串与占位符

At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage

模式字符串:

At {0} on {1},a destroyed {2} houses and caused {3} of damage.

格式化模式字符串

模式字符串:

•On {0}, a hurricance destroyed {1} houses and caused {2} of damage.

MessageFormat类

•MessageFormat(String pattern)

•实例化MessageFormat对象,并装载相应的模式字符串。

•format(object obj[])

•格式化输出模式字符串,参数数组中指定占位符相应的替换对象。

•format(new Object[ ]{date, new Integer(99), new Double(1E7) })

格式化模式字符串

String pattern = "On {0}, a hurricance destroyed {1} houses and caused "+ "{2} of damage.";
MessageFormat msgFmt = new MessageFormat(pattern,Locale.US);
//准备参数数组
String datetime = "Jul 3, 1998 12:30 PM";
Date date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
DateFormat.SHORT, Locale.US).parse(datetime);
Object [] msgArgs = {date, new Integer(99),new Double(1E7)};
//执行格式化操作
String result = msgFmt.format(msgArgs);
System.out.println(result);

模式字符串与占位符

占位符有三种方式书写方式:

•{argumentIndex}: 0-9 之间的数字,表示要格式化对象数据在参数数组中的索引号

•{argumentIndex,FormatType}: 参数的格式化类型

•{argumentIndex,formatType,FormatStyle}: 格式化的样式,它的值必须是与格式化类型相匹配的合法模式、或表示合法模式的字符串。

模式字符串与占位符

String pattern = "At {0, time, short} on {0, date}, {1} destroyed'\n'"+ "{2} houses and caused {3, number, currency} of damage.";
String datetimeString = "Jul 3, 1998 12:30 PM";
MessageFormat msgFmt = new MessageFormat(pattern,Locale.US);
Date date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
DateFormat.SHORT,Locale.US).parse(datetimeString);
String event = "a hurricance";
Object []msgArgs = {date, event, new Integer(99), new Double(1E7)};
String result = msgFmt.format(msgArgs);
System.out.println(result);
package cn.itcast.web.jsp.i18n;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale; //演示MessageFormat的用法
public class Demo4 {
public static void main(String[] args) throws Exception {
//模式字符串,即含有{0}占位符的字符中
String pattern = "On {0}, a hurricance destroyed {1} houses and caused {2} of damage.";
//创建MessageFormat类
MessageFormat mf = new MessageFormat(pattern,Locale.US);
String message = mf.format(new Object[]{new Date(),99,"$1000000"});
System.out.println(message);
}
}
package cn.itcast.web.jsp.i18n;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale; //演示占位符的其他使用方式
public class Demo5 {
public static void main(String[] args) {
String pattern = "At {0, time, short} on {0, date}, {1} destroyed'\n";
MessageFormat mf = new MessageFormat(pattern,Locale.US);
String message = mf.format(new Object[]{new Date(),99});
System.out.println(message);
}
}