zoukankan      html  css  js  c++  java
  • Struts源码阅读心得之bean:message篇

    Struts中非常常用的有这样的一个标签:
    <bean:message key="welcome.title"/> 众所周知,这个标签做的事情是这样的:访问在struts-config.xml中定义的资源文件,一般是 application.properties,一般是这样定义的: < message-resources parameter="resources.application"/> 根据以上的定义,Struts将到WEB-INF/classes/resource/下去找application.properties文件,这是从 以上配置信息 的表面上看起来是这样,但通过查看Struts的源码,可以看到如下的代码:在 org.apache.struts.util.PropertyMessageResources类中,有如下的代码:通过这段代码,可以看到
    A、.properties扩展名是写死在代码中的,所以资源文件必须使用这个扩展名
    B、Struts并不是单纯去寻找application.properties文件,而是首先找到application,赋给name变量 然后加上下划线"_",然后再加上localeKey(如zh,en),然后再加上.properties
    C、确定了文件名之后,Struts使用了ClassLoader类的getResourceAsStream方法得到了一个InputStream
    D、然后Struts使用了java.util.Properties类的load方法,将资源文件中的所有资源读出放到了一个HashMap里面
    E、然后Struts就可以根据key值取出不同的message给前台了

    Code: Select all
            // 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 += ".properties";
            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.load(is);
                   
                } catch (IOException e) {
                    log.error("loadLocale()", e);
                } finally {
                    try {
                        is.close();
                    } catch (IOException e) {
                        log.error("loadLocale()", e);
                    }
                }
            }


    D步骤中的load方法可以参看JDK的帮助文档,load方法要求这个资源文件必须以ISO8859编码进行书写方能正确解析 所以,如果我们在资源文件中写入了中文,并在运行时出现了中文编码问题(?出现),那么只需确认您的资源文件是否是以ISO8859为编码进行书写的即可 另外,Struts在查找资源文件时,首先是按照如上的描述进行$Filename_$ Locale.properties文件的查找如果他找不到,那么他就会用默认的$Filename.properties来找,如果还找不到,那就报错 了这个Struts的查找顺序并不是我的杜撰,有如下Struts源码为证(这个方法是PropertyMessageResources.java中 的): public String getMessage(Locale locale, String key) {

    Code: Select all
    if (log.isDebugEnabled()) {
                log.debug("getMessage(" + locale + "," + key + ")");
            }

            // Initialize variables we will require
            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) {
                        messages.put(originalKey, message);
                        return (message);
                    }
                }
            }

            // As a last resort, try the default Locale
    ===================================这里可以看到Struts最后将localeKey赋空 ===================================这样资源文件就是$Filename.properties了
    localeKey = "";
    messageKey = messageKey(localeKey, key); ===================================loadLocale这个方法将读取资源文件,填入 HashMap ===================================这个方法的代码在上面已经列出来了
    loadLocale(localeKey);
    synchronized (messages) {
    message = (String) messages.get(messageKey);
    if (message != null) {
    messages.put(originalKey, message);
    return (message);
    }
    }

    // Return an appropriate error indication
    if (returnNull) {
    return (null);
    } else {
    return ("???" + messageKey(locale, key) + "???");
    }

    }

    至于这个$Locale的值是多少,通过很长时间的查找之后,发现了这样一些代码:在org.apache.struts.util.RequestUtils类中的600多行左右,有这样一个方法: public static Locale
    Code: Select all
    getUserLocale(HttpServletRequest request, String locale) {
            Locale userLocale = null;
            HttpSession session = request.getSession(false);

            if (locale == null) {
                locale = Globals.LOCALE_KEY;  //这个值是org.apache.struts.action.LOCALE
            }

            // Only check session if sessions are enabled
            if (session != null) {
                userLocale = (Locale) session.getAttribute(locale);
            }

            if (userLocale == null) {
                // Returns Locale based on Accept-Language header or the server default
                userLocale = request.getLocale();
            }

            return userLocale;
        }


    可以看出,Struts将Locale的实例对象放到了session中,但是他什么时候将这个对象放到session里面的,尚未找到(很多配置在 ActionServlet中读取并储存的,因为这个类是第一个启动的类,但这个类中没发现Locale对象的储存)
  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/super119/p/1988617.html
Copyright © 2011-2022 走看看