05-Struts1.3 Struts的转换器跟国际化

05-Struts1.3 Struts的转换器和国际化

 

一、Struts的转换器

 

    Struts对ActionForm的自动搜集过程如下:

        将页面数据放到map中,其中map的key为页面中的名称,map中的value为页面中的value值

        调用第三方BeanUtils的setProperties方法,将map中的值逐个设置到ActionForm实例上,对于ActionForm中的每个属性根据类型调用相应的Converter,然后调用相应的convert方法,将相应的字符串转换成ActionForm中指定的类型;

 

    Struts转换器默认可以把一个字符串转换成intfloatbyte等等一些基本类型而对于日期,则只能处理java.sql.Date中的yyyy-mm-dd格式的,这时候就需要自己写转换器Strutsconversion转换器,所有的表单提交的服务器上的都是字符串

 

    在传递表单数据的时候会遇到这种情况。在formbeen中或者实体类中定义的类型是Date,Integer等对象类型。那么类型为String类型的传递进去的时候无法完成数据转换。这就需要使用struts的转换器。

 

    自定义转换器的实现步骤:

        1、实现converter接口,实现convert方法

        2、将实现converter注册,通常情况采用servlet注册,采用servlet注册需要注意标签的配置,必须指定load-on-startup属性值或者,采用Struts plugin的方式注册

 

下面以日期为例:

<label>时间:</label><input type="text" name="time">

 

package org.lxh.converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.Converter;

/**
 * @author xudongwang 2011-4-28
 *
 */
public class UtilDateConverter implements Converter {

	@Override
	public Object convert(Class type, Object value) {
		System.out.println("进入自定义的转换器");
		Date date = null;
		if(value instanceof String) {
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			try {
				date = format.parse((String)value);
			} catch (ParseException e) {
				return null;
			}
		}
		return date;
	}
}

 

定义好converter以后要在项目中注册。为了保证项目启动后最初就进行注册可以考虑在ActionServlet中完成注册。所以我们可以写一个继承了ActionServlet类的Servelet类,并重构init方法进行注册。要注意的是,如果在web.xml文件中设置了初始参数convertNull为true。注册的代码要写在super.init()之后。因为ActionServlet的init方法会调用一个ConvertUtils.deregister()方法,把所有的转换器清除。

 

以上面的日期转换器为例,具体注册的代码如下:

package org.lxh.servlet;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.commons.beanutils.ConvertUtils;
import org.lxh.converter.UtilDateConverter;

/**
 * @author xudongwang 2011-4-28
 *
 */
public class UtilDateConverterServlet extends HttpServlet {

	@Override
	public void init() throws ServletException {
		System.out.println("进入servlet");
		//action在对form-bean进行赋值的时候当发现有java.util.Date.class类型的则进入UtilDateConverter的转换器
		//使用servlet是因为web.xml中进行配置使得服务器启动时就可以使用了
		ConvertUtils.register(new UtilDateConverter(), Date.class);
	}
}

 

注册完的同时不要忘记把自己定义的ActionServletweb.xml文件中配置好。这样表单中的日期文本就可以传入Date类型的属性中了。

web.xml: 

	<servlet>
		<servlet-name>utilDateConverterServlet</servlet-name>
		<servlet-class>org.lxh.servlet.UtilDateConverterServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

 

但是还有一个问题,当发生错误需要进行数据回显时,<html:text>标签会从formbeen中读取数据,这个时候读取出的是Date类型的toString方法显示出的值,不是原来自己填写的值了。

 

struts-config.xml: 

<form-beans>
	<form-bean name="loginForm" type="org.lxh.form.LoginForm"></form-bean>
</form-beans>

<action-mappings>
		<!-- 这里的name是通过map的键值对来进行匹配,同时通过conversion进行struts下的类型转换 -->
		<!-- unknown="true"表示如果没有xx.do则会跳转到错误页面 -->
		<action path="/login" name="loginForm" type="org.lxh.action.LoginAction"
			unknown="true">
			<forward name="error" path="/error.jsp"></forward>
			<forward name="success" path="/success.jsp"></forward>
		</action>
</action-mappings>

 

LoginAction 

public class LoginAction extends Action {
	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		LoginForm loginForm = (LoginForm)form;
	System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(loginForm.getTime()));

 

要想进行双向转换,struts1已经没法做到了。struts2才可以做到。要在struts1达到我们预期的效果,可以使用其他的途径。

 例如使用jstl的fmt标签。把formbeen中的Date类型的数据按一定格式转成String类型,然后再赋值给<html:text>。

 示例代码如下:

 <fmt:formatDate value="${userForm.user.birthday}" type="date" pattern="yyyy-MM-dd" var="birthday"/>

 日期:<html:text property="user.birthday" value="${birthday}"></html:text> <br/>

 

上面有提到一个convertNull的参数。这个参数的作用要说明一下。

 

当我们在实体类或者formbeen中定义属性时,若是基本数据类型,那么struts标签在初始化时会先初始化formbeen,那么这个基本数据类型会先初始化为默认值。比如int类型就是0.那么在载入表单页面时,数据就会显示为0.这样非常不理想,明明没有填入任何数据,会显示出0.那么我们可以定义这个基本数据类型为包装类型,比如int就可以定义为Integer。它的默认值是null,null在struts的表单标签中是不显示的。但是当我们在这个标签中不填任何数据,当提交发生错误需要数据回显时问题就来了。struts会自动把null进行转换。Integer类型的null会转化成0.显示出来又会是0.解决这个问题的办法就是设置convertNull为true或者1或者yes或者on还有1都可以。这个可以从源代码中看到。它的作用就是忽略自动null转换

 

二、国际化

    国际化是指应用程序运行时,可根据客户端请求来自的国家/地区、语言的不同而显示不同的界面,例如如果请求来自中文操作系统的客户端,则应用程序中的各种标签,错误提示和帮助等都使用中文

     Struts的国际化基于java的国际化,将中文转换成ascii

native2ascii 源文件生成的文件05-Struts1.3 Struts的转换器跟国际化

 或者在jdk中用native2ascii生成

 

a、java中的国际化:

 

    java程序的国际化思路是将应用程序中的标签、提示等信息放在资源文件中,每个程序需要所支持的国家/语言,都必须提供对应的资源文件,其资源文件是key-value对,每个资源文件中的key是不变的,但value则随着不同国家/语言而变化

 

    国际化主要通过如下三个类完成:

        java.util.resourceBundle:对应用于加载一个资源包

        java.util.Local:对应一个特定的国家/地区语言环境

        java.text.MessageFormat:用于将消息格式化

 

package org.lxh.demo;
import java.util.Locale;
import java.util.ResourceBundle;
/**
 * @author xudongwang 2011-5-5
 *
 */
public class Test {
	public static void main(String[] args) {
//		Locale locale = Locale.getDefault();
		Locale locale = new Locale("en", "us");
		ResourceBundle bundle = ResourceBundle.getBundle("myResource", locale);
		String name = (String)bundle.getObject("name");
		System.out.print(name);
	}
}

 

说明:

    java不可能支持所有国家和语言,可以通过Locale[] localeList = Locale.getAvailableLocales()获得java所支持的国家和语言的集合

myResource_en.properties(name=hello)
myResource_zh_CN.properties(name=\u5434\u4F73\u4FCA)
myResource_zh.properties(name=sss)

 

当使用第一种默认的方式时会使用myResource_zh_CN.properties资源文件

 

注意上面资源包的命名规则

 

 

b、Struts的国际化:

1、myResource_zh_CN.properties:

	name=\u7528\u6237\u540D\uFF1A
	error.name={0} please login again!

 

资源文件说明

    1myResource是国际化信息文件名资源文件的格式:资源文件名 + "_" + 语言码 + "_" + 国家码),放在src. 提供不同版本的国际化资源文件中文需要采用native2ascii转换成unicode

    2、加载资源文件的顺序:

       a、搜索所有国家和语言都匹配的资源文件

       b、如果上面的没有,在搜索语言匹配的文件

       c、最后搜索资源文件名匹配的文件

 

2、struts-config.xml: 

	<!-- 相当于ResourceBundle.getBundle("myResource", Locale.getDefault()); -->
	<message-resources parameter="myResource"></message-resources>

 

配置文件说明;

     1、message-resources元素中的parameter指定了资源文件的位置;

     2、Struts实现国际化,必须将ActionServlet配置成load-on-startup的servlet,只有这样才可以保证在启动应用时加载该资源文件;

  

3、jsp页面上: 

<bean:message key="name" />

 

说明:

     key属性对应了资源文件中的key,Struts会自动根据浏览器的语言设置,从资源文件中取得相应的value