struts中文问题和jsp是一样的
无非是页面加编码
用filter过滤请求编码
资源文件用native2ascii转码

解决方案 »

  1.   

    用.xml文件替代.properties文件来解决Struts的中文问题 
    -------------------------------------------------------------
    由于ApplicationResources.properties文件不支持中文。
    前面有文章提到用native2ascii.exe对文件进行编码的转换来解决这个问题,我也提到过修改PropertyMessageResources.java源文件来解决这个问题。
    但Struts1.1b2出来以后,我前面提到的那种修改PropertyMessageResources.java的方法不行了,因为在Struts中多个类使用到PropertyMessageResources类。直接进行编码转换将导致其它类无法正常运行。
    在1.1b2版本中你依然可以使用native2ascii.exe对文件编码来解决中文问题。
    不过在这里提供另一种方法来解决中文问题,让你可以有更多的选择。
    这里使用了JDOM来解析XML文件,取得指定的文字信息。
    对PropertyMessageResources.java文件的修改如下:package org.apache.struts.util;import org.jdom.Element;
    import org.jdom.Document;
    import org.jdom.input.SAXBuilder;
    import java.util.List;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Properties;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;public class PropertyMessageResources extends MessageResources
    {
        public PropertyMessageResources(MessageResourcesFactory factory,String config)
        {
            super(factory, config);
            log.info("Initializing, config='" + config + "'");
        }
        
        public PropertyMessageResources(MessageResourcesFactory factory,String config, boolean returnNull)
        {
            super(factory, config, returnNull);
            log.info("Initializing, config='" + config + "', returnNull=" + returnNull);
        }
        
        protected HashMap locales = new HashMap();
        
        protected static final Log log = LogFactory.getLog(PropertyMessageResources.class);
        
        protected HashMap messages = new HashMap();
        
        public String getMessage(Locale locale, String key)
        {
            if (log.isDebugEnabled())
            {
                log.debug("getMessage(" + locale + "," + key + ")");
            }
            
            String localeKey = localeKey(locale);
            String originalKey = messageKey(localeKey, key);
            String messageKey = null;
            String message = null;
            int underscore = 0;
            boolean addIt = false;  // Add if not found under the original key
            // Loop from specific to general Locales looking for this message
            while (true)
            {
                // Load this Locale's messages if we have not done so yet
                loadLocale(localeKey);
                // Check if we have this key for the current locale key
                messageKey = messageKey(localeKey, key);
                synchronized (messages)
                {
                    message = (String) messages.get(messageKey);
                    if (message != null)
                    {
                        if (addIt)
                            messages.put(originalKey, message);
                        return (message);
                    }
                }
                
                // Strip trailing modifiers to try a more general locale key
                addIt = true;
                underscore = localeKey.lastIndexOf("_");
                if (underscore < 0)
                    break;
                localeKey = localeKey.substring(0, underscore);
            }
            // Try the default locale if the current locale is different
            if (!defaultLocale.equals(locale))
            {
                localeKey = localeKey(defaultLocale);
                messageKey = messageKey(localeKey, key);
                loadLocale(localeKey);
                synchronized (messages)
                {
                    message = (String) messages.get(messageKey);
                    if (message != null)
                    {
                        if (addIt)
                            messages.put(originalKey, message);
                        return (message);
                    }
                }
            }
            // As a last resort, try the default Locale
            localeKey = "";
            messageKey = messageKey(localeKey, key);
            loadLocale(localeKey);
            synchronized (messages)
            {
                message = (String) messages.get(messageKey);
                if (message != null)
                {
                    if (addIt)
                        messages.put(originalKey, message);
                    return (message);
                }
            }
            // Return an appropriate error indication
            if (returnNull)
                return (null);
            else
                return ("???" + messageKey(locale, key) + "???");
        }
      

  2.   


        // ------------------------------------------------------ Protected Methods
        /**
         * Load the messages associated with the specified Locale key.  For this
         * implementation, the <code>config</code> property should contain a fully
         * qualified package and resource name, separated by periods, of a series
         * of property resources to be loaded from the class loader that created
         * this PropertyMessageResources instance.  This is exactly the same name
         * format you would use when utilizing the
         * <code>java.util.PropertyResourceBundle</code> class.
         *
         * @param localeKey Locale key for the messages to be retrieved
         */
        protected void loadLocale(String localeKey) {        if (log.isTraceEnabled()) {
                log.trace("loadLocale(" + localeKey + ")");
            }        // Have we already attempted to load messages for this locale?
            synchronized (locales) {
                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;
            String xmlName = name + ".xml";
            name += ".properties";
            InputStream is = null;
            Properties props = new Properties();        // Load the specified property resource
            try {
                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) {
                    props.load(is);
                    is.close();
                }
                else
                {
                    is = classLoader.getResourceAsStream(xmlName);
                    if (is != null)
                    {
                        org.jdom.input.SAXBuilder builder = new SAXBuilder();
                        org.jdom.Document doc = builder.build(is);
                        org.jdom.Element root = doc.getRootElement();
                        loadFromElement(localeKey,root.getName(),root);
                        is.close();
                    }
                }
                if (log.isTraceEnabled()) {
                    log.trace("  Loading resource completed");
                }
            } catch (Throwable t) {
                log.error("loadLocale()", t);
                if (is != null) {
                    try {
                        is.close();
                    } catch (Throwable u) {
                        ;
                    }
                }
            }        // Copy the corresponding values into our cache
            if (props.size() < 1)
                return;
            synchronized (messages) {
                Enumeration names = props.keys();
                while (names.hasMoreElements()) {
                    String key = (String) names.nextElement();
                    if (log.isTraceEnabled()) {
                        log.trace("  Saving message key '" +
                                  messageKey(localeKey, key));
                    }
                    messages.put(messageKey(localeKey, key),
                                 props.getProperty(key));
                }
            }    }    private void loadFromElement(String localeKey,String key,org.jdom.Element element)
        {
            if (element.hasChildren())
            {
                List children = element.getChildren();
                for (int i=0;i < children.size();i++)
                {
                    org.jdom.Element child = (org.jdom.Element)children.get(i);
                    String newKey = key + "." + child.getName();
                    loadFromElement(localeKey,newKey,child);
                }
            }
            else
            {
                messages.put(messageKey(localeKey, key),element.getText());
            }
        }
    }编译这个文件你需要到http://www.jdom.org上取得它的bete8版本
    并将jdom.jar和xerces.jar加入到你的CLASSPATH里面。
    当然Struts.jar也要加到CLASSPATH里面。
    编译完以后用这个PropertyMessageResources.class替换掉struts.jar里面的相同文件。
    然后重新将struts.jar打包。
    大家如果仔细看上面的代码,会发现替换掉这个类以后并不影响到struts的使用,你依然可以使用它默认的.properties文件的方式。
    但如果你想试试用.xml文件来作为.properties的替代的话,你需要把你原来的.properties文件移去,并在同样的目录编辑一个新的xml文件。
    它的格式象下面的描述一样:
    <?xml version="1.0" encoding="GB2312"?>
    <letter>
        <index>
            <title>用户登录</title>
            <description>基于Struts1.1.b2架构的教学实例</description>
            <copyright>深圳维豪多媒体网络有限公司版权所有 2002</copyright>
            <header>请输入用户名和密码登录</header>
            <usernameLabel>用户名</usernameLabel>
            <passwordLabel>密码</passwordLabel>
            <butLogonLabel>登录</butLogonLabel>
            <butRegLabel>注册</butRegLabel>
        </index>
        <error>
            <nothisuser>对不起,这个用户不存在</nothisuser>
            <passworderror>密码错误</passworderror>
        </error>
    </letter>
    然后你可以通过
    <bean:message key="letter.index.tilte"/>
    <bean:message key="letter.error.nothisuser"/>
    等来引用到xml文件中的内容。大家如果研究过jive的源代码的话一定对这种方式的引用不陌生。
    我刚刚完成这个类的修改,并没有做太多的测试,如果有问题的话请尽可能的自己解决,并将问题和修改方法提交到这里来。注意:
    1.如果在同一个目录下有ApplicationResources.properties和ApplicationResources.xml的话,将优先使用ApplicationResources.properties文件。
    2.在你发布的应用中需要在/WEB-INF/lib下添加jdom.jar和xerces.jar两个包才可以使改类正常运行。 
      

  3.   

    这种解决struts中文问题的方法完全是错误的。
    struts提供资源文件完全是为了支持国际化,ApplicationResources.properties根本没有必要出现中文汉字,其他语种的文件都放在ApplicationResources_zh.properties这样的文件中,struts会自动根据浏览器来选择对应的语言。
    楼上的不会就不要乱来,居然还需要修改源文件。
    楼主,这不是倒分贴吧?
      

  4.   

    同意楼上老兄的意见,而且要用JDK1.4下的NATIVE2ASCII命令,然后配置你的ApplicationResources.properties就OK了.
      

  5.   

    如果是资源文件就用native2ascii转码,其他的中文显示与jsp一致。