`

struts1.3 读取资源文件乱码的另一种解决方法

阅读更多
在网上找了一下资料,很多文章推荐使用native2ascii命令。

个人觉得很不方便,因为开发过程中资源文件修改比较频繁,每次都要运行脚本。

用PropertiesEditor插件。

还是很不方便,每个开发客户端都要装,很麻烦。

另外,资源文件,特别是国际化的时候,通常开发人员都喜欢用UTF-8来编码,以方便修改。但调试的时候就会出问题。

解决办法思路:因为struts是使用Classloader.load(InputStream)来加载资源文件的。所以必须继承修改加载资源文件实现类org.apache.struts.util.PropertyMessageResources的loadLocale方法。第二,兼顾资源文件修改的方便性,最好使资源文件xml化。这样只要标准的xml IDE就可以方便修改,从根本上避免的字符集和IDE相关联的问题。而且可以利用JDK1.5的特性:Properties有一个loadFromXML(InputStream)方法可以方便加载。

解决办法:继承和修改资源文件加载相关的两个实现类:
com.yourcompany.struts.util.XMLPropertyMessageResources继承
org.apache.struts.util.PropertyMessageResources
package com.yourcompany.struts.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Properties;

import org.apache.struts.util.MessageResourcesFactory;
import org.apache.struts.util.PropertyMessageResources;

public class XMLPropertyMessageResources extends PropertyMessageResources {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3701712123553100102L;

	public XMLPropertyMessageResources(MessageResourcesFactory factory,
			String config, boolean returnNull) {
		super(factory, config, returnNull);
	}

	public XMLPropertyMessageResources(MessageResourcesFactory factory,
			String config) {
		super(factory, config);
	}

	@Override
	protected synchronized void loadLocale(String localeKey) {
		if (log.isTraceEnabled()) {
            log.trace("loadLocale(" + localeKey + ")");
        }

        // Have we already attempted to load messages for this locale?
        if (locales.get(localeKey) != null) {
            return;
        }

        locales.put(localeKey, localeKey);

        // Set up to load the property resource for this locale key, if we can
        String name = config.replace('.', '/');

        if (localeKey.length() > 0) {
            name += ("_" + localeKey);
        }

        name += ".xml";//此处修改官方代码,便于IDE环境编辑XML

        InputStream is = null;
        Properties props = new Properties();

        // Load the specified property resource
        if (log.isTraceEnabled()) {
            log.trace("  Loading resource '" + name + "'");
        }

        ClassLoader classLoader =
            Thread.currentThread().getContextClassLoader();

        if (classLoader == null) {
            classLoader = this.getClass().getClassLoader();
        }

        is = classLoader.getResourceAsStream(name);

        if (is != null) {
            try {
                props.loadFromXML(is);//此处修改官方代码,加载XML
            } catch (IOException e) {
                log.error("loadLocale()", e);
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("loadLocale()", e);
                }
            }
            if (log.isTraceEnabled()) {
                log.trace("  Loading resource completed");
            }
        } else {
            if (log.isWarnEnabled()) {
                log.warn("  Resource "+name+" Not Found.");
            }
        }


        // Copy the corresponding values into our cache
        if (props.size() < 1) {
            return;
        }

        synchronized (messages) {
            Iterator names = props.keySet().iterator();

            while (names.hasNext()) {
                String key = (String) names.next();

                if (log.isTraceEnabled()) {
                    log.trace("  Saving message key '"
                        + messageKey(localeKey, key));
                }

                messages.put(messageKey(localeKey, key), props.getProperty(key));
            }
        }
	}
	
}


com.yourcompany.struts.util.XMLMessageResourcesFactory继承
org.apache.struts.util.PropertyMessageResourcesFactory
package com.yourcompany.struts.util;

import org.apache.struts.util.MessageResources;
import org.apache.struts.util.PropertyMessageResourcesFactory;

public class XMLMessageResourcesFactory extends PropertyMessageResourcesFactory {

	 public MessageResources createResources(String config) {
        XMLPropertyMessageResources messageResources =
               new XMLPropertyMessageResources(this, config, this.returnNull);//此处修改官方代码,使用修改后的资源加载类
        String mode = null;
        if (getConfig() != null) {
            mode = getConfig().getProperty("mode");
        }
        messageResources.setMode(mode);
        return messageResources;
    }
}



修改struts-config.xml的此行为:
<message-resources parameter="com.yourcompany.struts.message.ApplicationResources" factory="com.yourcompany.struts.util.XMLMessageResourcesFactory"/>


你的资源文件改为如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>Resources for default
	</comment>
	<entry key="commons.validate.notnull">can't be empty</entry>
	
	<entry key="vo.Packageinfo.packageId">Package ID</entry>
	<entry key="vo.Packageinfo.packageAlias">Package Alias</entry>
	<entry key="vo.Packageinfo.packageName">Package Name</entry>
	<entry key="vo.Packageinfo.packagePrices">Package Prices</entry>
	<entry key="vo.Packageinfo.productLimit">Product Limit</entry>
	<entry key="vo.Packageinfotbl.description">Description</entry>
</properties>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>Resources for zh_CN
	</comment>
	<entry key="commons.validate.notnull">不能为空</entry>
	
	<entry key="vo.Packageinfo.packageId">套餐ID</entry>
	<entry key="vo.Packageinfo.packageAlias">套餐别名</entry>
	<entry key="vo.Packageinfo.packageName">套餐名</entry>
	<entry key="vo.Packageinfo.packagePrices">套餐价格</entry>
	<entry key="vo.Packageinfo.productLimit">允许发布产品数量</entry>
	<entry key="vo.Packageinfo.description">描述信息</entry>
</properties>


如果已经有经过native2ascii转换过的资源文件的。可以使用一下代码转换:
Properties props = new Properties();
props.load(new FileInputStream(...));
props.storeToXml(new FileOutputStream(...));
.....


总结:如果是团队开发,修改资源文件的加载类,只需要做一次就可以让团队开发人员省却重复的工作。
2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics