struts框架支持语言 (struts2语言)

国际化

• 服务器按照用户浏览器上选择的语言给出提示

• 国际化 [ Internationalization ] -- 缩写为 I18N -- 取开头和结尾两个字母,中间有 18 个字母

• 种类:

○ 硬编码国际化 [ 静态国际化 ] -- 程序中不变的代码 [ jsp 页面中的静态代码 ]

§ 硬编码国际化实例 -- 依据 locale 信息

§ 硬编码国际化实例 -- 自动切换

○ 动态信息国际化 -- 程序中动态生成的代码 -- 提示信息 / 异常信息

§ 动态信息国际化

§ 动态信息国际化 -- 编程式异常

• 国际化文件组成:

○ baseName +[ 基名 + _语言名_国家名.properties ]

如:MessageResources_en_US.properties 语言小写,国家大写

○ baseName [ 基名.properties ]

§ 如:MessageResources.properties -- 默认国际化资源文件,一般默认为英文

○ 项目中没有对应语言的国际化资源文件就使用默认国际化资源文件

○ 默认国际化资源文件:

• 配置:

§ 如果浏览器使用的是法文,在项目下没有找到法文国际化资源文件 -- 看系统用的语言 -- 寻找系统语言的国际化资源文件

§ 如果用户系统下所用的语言在项目中也没有对应的国际化资源文件 -- 使用默认国际化资源文件 [ 一般为英文 ]

§ 如果浏览器使用的是法文,在项目下没有找到法文国际化资源文件 -- 看系统用的语言 -- 寻找系统语言的国际化资源文件

§ 如果用户系统下所用的语言在项目中也没有对应的国际化资源文件 -- 使用默认国际化资源文件 [ 一般为英文 ]

○ 在 struts-config.xml 主配文件中加 <message-resources> 标签配置信息

<message-resources parameter="res.MessageResources"/>

§ 该标签中指定了国际化文件的基名和位置,位置默认在 src 下

§ res -- src 下的一个子目录

○ 将国际化文件放在指定目录下

• 国际化资源文件格式:

○ 作为 properties 文件,为 Map 格式 -- 有 key 和 value

§ 一个项目中各个国际化资源文件的 key 都是一致的,value 根据各国语言进行相应的更改

○ 中文国际化资源文件:

§ properties 文件中中文字符为 ASCII 码 -- struts 框架无法识别中文字符

§ 将汉字变为 ASCII 码:

□ native2ascii 指令:

struts2语言,struts用什么语言开发

在文件所在目录下进行指令

□ 将源文件直接转换成中文的国际化资源文件:

struts2语言,struts用什么语言开发

• 缺点:代码可读性差

在文件所在目录下进行指令

native2ascii*ex.e** o.properties MessageResources_zh_CN.properties 将源文件的 properties 转换为中文的符合要求的国际化资源文件

硬编码国际化实例 -- 依据 locale 信息

• 使用中文显示:

○ 客户端发出请求:

§ http 协议头上会自动带有 locale 信息 [ 客户端所在的浏览器的语言信息 ]

§ Tomcat 创建 request 接收请求字符串 / 请求参数 / cookie / locale / IP 地址

§ Tomcat 取得该用户对应的 session -- 如果是第一次访问,会自动创建 session / 不是第

一次访问,已有 session

§ 从 request 内置对象中取得 locale 信息

§ 将从 request 内置对象中取得的 locale 信息设到 session 中,属性名为

Globals.LOCALE_KEY session.setAttribute(Globals.LOCALE_KEY, locale);

○ 使用国际化资源文件:

§ 针对国际化产生的一个 struts 标签:[ 动态代码,服务器执行 ]

□ <a href="login1.do"><bean:message key="user.button.login"/></a><br>浏览器显示【登录】

® 先到该用户对应的 session 中取得封装的 locale 信息session.getAttribute( Globals.LOCALE_KEY ); -- 封装了语言名_国家名

® 到 struts-config.xml 中去找 <message-resources> 标签,从而取得国际化资源文件的基名和位置

◊ 通过 struts 的 Bean-message 标签可以找到国际化资源文件

® 通过标签中的 key,找到国际化资源文件中的 value -- user.button.login=\u767B\u5F55 [ 登录 ]

• 使用英文显示:[ 浏览器的语言设置为英文 ]

○ 客户端发出请求:

§ http 协议头上会带有 locale 信息 -- 此时 locale 信息中为英文

§ Tomcat 创建 request 对象接收 locale 信息

§ Tomcat 将从 request 中取得的 locale 信息设到与该用户对应的 session 中

○ 执行 index.jsp 页面:

§ 处理标签:

<a href="login1.do"><bean:message key="user.button.login"/></a><br>浏览器显示【Login】

□ 此时为英文国际化资源文件

□ 通过标签中的 key,找到国际化资源文件中的 value -- user.button.login=Login

○ 用户通过超链接发出请求,Tomcat 将 locale 信息设到 session 中后将请求提交给 struts: 请求字符串:http://127.0.0.1:8080/test/login1.do

<action path="/login1" forward="/login.jsp"
>
</action>

○ struts 在截取到 path="/login1" 字符串后立即进行 locale 信息的处理: String path = processPath(request, response); processLocale(request, response);

------------------------- processLocale(request, response)

protected void processLocale( HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); // 取得 session
// 判断 session 中是否有 locale 信息,有就不再设置,没有就从 request 中取得信息并设置到 session 中,属性名为 Globals.LOCALE_KEY if (session.getAttribute(Globals.LOCALE_KEY) != null) { return; }
Locale locale = request.getLocale();
if (locale != null) { session.setAttribute(Globals.LOCALE_KEY, locale); }
}

§ 在浏览器上改完语言要重启浏览器 -- 产生一个新的 session,不然原来的 session 里有原来为中文的 locale 信息,无法更改成功

○ 由于 session 中设置的国际化资源文件为英文 -- 该用户发出任何请求,静态 jsp 页面文字都为英文 -- 英文国际化资源文件

硬编码国际化实例 -- 自动切换

• 进入首页:

------------------------- index.jsp

<a href="changelang.do?lang=zh">中文</a><br>

<a href="changelang.do?lang=en">英文</a>

• 用户点击超链接发出请求,请求字符串:http://127.0.0.1:8080/test/changelang.do?lang=zh

• struts 截取到 path="/changelang":

• struts 处理 locale 信息 -- processLocale():

○ 拿到当前用户对应的 session

○ 看 session 中是否有属性名为 Globals.LOCALE_KEY 的属性值

§ 如果有值就使用原值

§ 如果没有,从 request 中拿到 locale 信息并将取得的 locale 信息设置到 session 中,属

性名为 Globals.LOCALE_KEY

• 在 struts-config.xml 中寻找 path="/changelang" 的 <action> 标签:

<action path="/changelang" type="com.bjsxt.struts.ChangeLanguageAction"
>
<forward name="index" path="/index.jsp"/>
</action>

• 通过 type 创建出 Action 对象,并执行 Action 中的 execute() 方法:

------------------------- ChangeLanguageAction.java

String lang = request.getParameter("lang"); // 从用户发出的请求中获取参数名为lang 的参数值Locale currentLocale = Locale.getDefault(); // 给 Locale 一个默认值 -- 默认值为系统语言

if ("zh".equals(lang)) {

currentLocale = new Locale("zh", "CN"); // 如果用户请求中参数名为 lang 的参数值为中文 -- 给 Locale 对象重新赋值为中文国际化资源文件

}else if("en".equals(lang)) {

currentLocale = new Locale("en", "US"); // 如果用户请求中参数名为 lang 的参数值为英文 -- 创建一个对应英文国际化资源文件的 locale 对象

}

this.setLocale(request, currentLocale); // this 代表 ChangeLanguageAction,将自己创建好的locale 信息设置到 session 中

return mapping.findForward("index");

------------------------- setLocale(request, currentLocale)

protected void setLocale(HttpServletRequest request, Locale locale) { HttpSession session = request.getSession();
if (locale == null) { locale = Locale.getDefault(); } session.setAttribute(Globals.LOCALE_KEY, locale);
}

• 国际化资源文件的动态切换

○ 通过 execute() 方法根据用户超链接选择的参数,重新创建相应的locale 对象并设置到 session 中属性名为 Globals.LOCALE_KEY 的属性值中 -- 可以人为改变先前根据浏览器系统语言而设置的locale 信息

动态信息国际化

• 特点:

○ 国际化资源文件中有动态信息的动态填充位置

• 实例:

§ 如:user.login.success = {0},登录成功

§ {0} -- 动态填充位置

○ 登录界面:

struts2语言,struts用什么语言开发

<form action="login.do" method="post">
<bean:message key="user.username"/>:<input type="text" name="username"><br>
<bean:message key="user.password"/>:<input type="password" name="password"><br>
<input type="submit" value="<bean:message key="user.button.login"/>">
</form>

○ 通过Bean-message 标签可以拿到国际化资源文件 -- 浏览器显示【User Name】【Password】

○ 用户输入用户名和密码,提交请求,请求字符串:http://127.0.0.1:8080/test/login.do

○ struts 截取到 path="/login":

○ struts 处理 locale 信息 -- processLocale():

○ 拿到当前用户对应的 session

○ 看 session 中是否有属性名为 Globals.LOCALE_KEY 的属性值

□ 如果有值就使用原值

□ 如果没有,从 request 中拿到 locale 信息并将取得的 locale 信息设置到 session 中,属性名为 Globals.LOCALE_KEY

○ 在 struts-config.xml 中寻找 path="/login" 的 <action> 标签:

<form-beans>

<form-bean name="loginForm" type="com.bjsxt.struts.LoginActionForm"/>
</form-beans>
<action path="/login" type="com.bjsxt.struts.LoginAction" name="loginForm" scope="request"
validate="false"
>
<forward name="success" path="/login_success.jsp"/>
<forward name="error" path="/login.jsp"/>
</action>

○ 通过 name 找 ActionForm -- 创建出 ActionForm 对象后将表单数据收集到 LoginActionForm: private String username; -- "admin"

private String password; -- "admin"

○ 通过 type 创建出 Action 对象,并执行 Action 中的 execute() 方法:

------------------------- LoginAction.java LoginActionForm laf = (LoginActionForm)form; String username = laf.getUsername();

String password = laf.getPassword();

ActionMessages messages = new ActionMessages(); // 定义一个 ActionMessages

UserManager.getInstance().login(username, password); // 执行业务对象的 login() 方法,顺利执行完后进行以下代码

ActionMessage message = new ActionMessage( "user.login.success", username ); messages.add("loginSuccess1", message);

ActionMessage message1 = new ActionMessage("user.login.success", username); // 虽然存放的信息一样,但不是同一个对象

messages.add("loginSuccess2", message1); this.saveMessages(request, messages); return mapping.findForward("success");

□ 即 -- ActionMessage message = new ActionMessage( "user.login.success", new Object[]{username} );

□ 创建国际化消息文本对象 -- new ActionMessage( "国际化资源文件中的 key", 要填入到对应的 value 中的填充符中的信息 )

® ActionMessage 的 key 就是国际化资源文件中的 key,value 是一个 Object 数组对象

® Object 数组对象中的数据作为国际化资源文件中的动态填充符

□ 通过 key 找到国际化资源文件中对应的 value -- user.login.success={0},Login Success

□ 用 username 的值去填充国际化资源文件中对应的 value 中的填充符 -- {0}

□ 如果有多个填充位置,使用 Object 数组对象来进行填充 -- 数组中第一个元素填充到 {0},第二个元素填充到 {1} …

® 如:user.login.success={0} login success {1}{2}

® ActionMessage message = new ActionMessage( "user.login.success", new Object[]{ username, username, username} )

□ 必须将国际化消息文本对象 ActionMessage 放进 ActionMessages 对象中的一个 Map 集合 messages 中

® protected HashMap messages = new HashMap(); -- 专门用来存放国际化消息文本对象

□ ActionMessages 内部有一个 Map 集合,ActionMessages 不是集合

□ 此时 messages 里有两个元素:

® key="loginSuccess1",value 为第一个国际化消息文本对象 message

® key="loginSuccess2",value 为第二个国际化消息文本对象 message1

------------------------- saveMessages(request, messages)

request.setAttribute(Globals.MESSAGE_KEY, messages);

® 传递国际化消息文本

® 将存放了消息文本对象的ActionMessages 对象放进 request 内置对象中,属性名为 Globals.MESSAGE_KEY

□ 将 ActionMessages 对象设入 request 内置对象中之后,Action 返回给 struts 一个封装了转向路径的 ActionForward 对象

○ struts 解析 ActionForward 对象后转向相应的 jsp 页面 -- login_success.jsp:

<html:messages id="msg" message="true" property="loginSuccess1">
<bean:write name="msg"/>
</html:messages>
○ html-messages 标签只能取得 ActionMessages,不能取 ActionMessage
○ <html:messages id="msg" message="true" property="loginSuccess1">

□ 先从该用户对应的 session 里找属性名为 Globals.LOCALE_KEY 的属性值 -- 取得国际化资源文件的 locale 信息

□ 到 struts-config.xml 配置文件中找 <message-resources> 标签中找 parameter 属性 -- 取得国际化资源文件的基名和位置

□ 根据 locale 信息和国际化资源文件的基名和位置找到相应的国际化资源文件

□ 从该请求对应的 request 内置对象中取得属性名为 Globals.MESSAGE_KEY 的属性值 -- 取得 ActionMessages 对象

□ 取得 ActionMessages 对象后,到对象中的 messages 集合中找 key 为 loginSuccess1 的 value -- 取得国际化消息文本对象 ActionMessage

□ 将 ActionMessage 对象放到 page 内置对象中,属性名为 msg

○ <bean:write name="msg"/>

□ 从 scope 中找 key 为 msg 的属性值 -- 取得 ActionMessage 对象

□ 通过解析 ActionMessage -- 调用 getkey() 方法 -- 取得 ActionMessage 中的 key="user.login.success"

□ 通过取得的 key,到国际化资源文件中找具有相同的 key 的 value -- user.login.success={0},Login Success

□ 通过解析 ActionMessage -- 调用 getValue() 方法 -- 取得 username,并将 username 的值填充到国际化资源文件中的填充位置上

□ 将填充后的信息作为 Bean-write 的标签值返回浏览器显示【admin,Login Success】

--------------------------------------------------------------------------------------------------------------------------------------

<html:messages id="msg" message="true">

<bean:write name="msg"/>

</html:messages>

○ 省略了 property 属性后,处理所有的 ActionMessage

○ <html:messages id="msg" message="true">

□ 取得国际化资源文件

□ 从该请求对应的 request 内置对象中取得属性名为 Globals.MESSAGE_KEY 的属性值 -- 取得 ActionMessages 对象

□ 将 ActionMessages 对象内部 Map 集合 messages 下的所有 value 值都取出 -- 取得 message / message1 两个 ActionMessage 对象

□ 依次将 message / message1 交给 page 内置对象,属性名为 msg

○ <bean:write name="msg"/>

□ 从 scope 中找 key 为 msg 的属性值 -- 取得 ActionMessage 对象 message

□ 通过解析 ActionMessage -- 调用 getkey() 方法 -- 取得 message 中的 key="user.login.success"

□ 通过取得的 key,到国际化资源文件中找具有相同的 key 的 value -- user.login.success={0},Login Success

□ 通过解析 message -- 调用 getValue() 方法 -- 取得 username,并将 username 的值填充到国际化资源文件中的填充位置上

□ 再次取得 key 为 msg 的属性值 -- 取得 ActionMessage 对象 message1

□ 通过解析 ActionMessage -- 调用 getkey() 方法 -- 取得 message1 中的 key="user.login.success"

□ 通过取得的 key,到国际化资源文件中找具有相同的 key 的 value -- user.login.success={0},Login Success

□ 通过解析 message1 -- 调用 getValue() 方法 -- 取得 username,并将 username 的值填充到国际化资源文件中的填充位置上

□ 将填充后的信息作为 Bean-write 的标签值返回浏览器显示【admin,Login Success admin,Login Success】

--------------------------------------------------------------------------------------------------------------------------------------

<html:messages id="msg">

<bean:write name="msg"/>浏览器没有任何显示

</html:messages>

□ message 属性:

® message="true":告诉标签,从 request 中的 Globals.MESSAGE_KEY 中取值

® 不写 message 属性则默认为 false,从 request 中的 Globals.ERROR_KEY 中取值