<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ALL is Well!

    敏捷是一條很長的路,摸索著前進著

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks

    他山之石可以攻玉。
    Spring為我們提供了一個PropertyPlaceholderConfigurer,它能夠使Bean在配置時引用外部屬性文件。
    可以將BeanFactory定義中的一些屬性值放到另一個單獨的標準Java Properties文件中。
    我們在部署應用時只需要在屬性文件中對一些屬性進行修改,而不用對主XML定義文件或容器所用文件進行復雜和危險的修改。
    讓我們看看下面的例子片段:

        <bean id="propertyConfigurer"
            class
    ="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            
    <property name="locations">
                
    <list>      
                    
    <value>classpath:jdbc.properties</value>
                
    </list>      
            
    </property>      
        
    </bean> 
        
    <bean id="proxoolDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            
    <property name="driverClassName" value="${driver}" />
            
    <property name="url" value="${dburl}" />
            
    <property name="username" value="${username}" /> 
            
    <property name="password" value="${password}" />
        
    </bean>

    jdbc.properties:

    driver=oracle.jdbc.OracleDriver
    dburl=jdbc:oracle:thin:@localhost:1521:root
    username=myusername
    password=mypassword


    相信上面的配置大家都用到過,
    如此配置后 xml 文件中的 "${***}"占位符會被替換成jdbc.properties中對應的屬性值。

    現在我有一個需求,要求在DB中配置一些參數,如數據庫的用戶名、密碼等,我在參數中提供一個模板,
    形如 jdbc:oracle:thin:@${host}:${port:1521}:${service_name}。
    然后host、port、service_name從參數表中取得,然后進行替換。
    于是,我想到了Spring為我們提供的PropertyPlaceholderConfigurer.java,在看了代碼之后,將字符串替換的代碼摘出來,為我的需求服務。
    下面是我摘出來的字符串解析替換的輔助類:

    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;

    import org.springframework.util.StringUtils;

    public class PlaceholderUtils {

        
    /** Default Holder prefix: "${" */
        
    public static final String DEF_HOLDER_PREFIX            = "${";

        
    public static final int    DEF_HOLDER_PREFIX_LEN        = 2;

        
    /** Default Holder suffix: "}" */
        
    public static final String DEF_HOLDER_SUFFIX            = "}";

        
    public static final int    DEF_HOLDER_SUFFIX_LEN        = 1;
        
    /** Never check system properties. */
        
    public static final int    SYSTEM_PROPERTIES_MODE_NEVER = 0;

        
    /**
         * Check system properties if not resolvable in the specified properties.
         * This is the default.
         
    */

        
    public static final int    SYS_PROPS_MODE_FALLBACK      = 1;

        
    /**
         * Check system properties first, before trying the specified properties.
         * This allows system properties to override any other property source.
         
    */

        
    public static final int    SYS_PROPS_MODE_OVERRIDE      = 2;

        
    /**
         * Parse the given String value recursively, to be able to resolve
         * nested Holders (when resolved property values in turn contain
         * Holders again).
         * 
         * 
    @param strVal
         *            the String value to parse
         * 
    @param props
         *            the Properties to resolve Holders against
         * 
    @param visitedHolders
         *            the Holders that have already been visited
         *            during the current resolution attempt (used to detect circular references
         *            between Holders). Only non-null if we're parsing a nested Holder.
         * 
    @throws Exception
         * 
    @throws AppException
         *             if invalid values are encountered
         * 
    @see #resolveHolder(String, java.util.Properties, int)
         
    */

        
    public static String parse(String strVal) throws Exception {
            Set
    <String> visitedHolders = new HashSet<String>();
            
    return parse(strVal, null, visitedHolders, false);
        }


        
    public static String parse(String strVal, Map<Object, Object> props) throws Exception {
            Set
    <String> visitedHolders = new HashSet<String>();
            
    return parse(strVal, props, visitedHolders, false);
        }


        
    public static String parse(String strVal, boolean ignoreBadHolders) throws Exception {
            Set
    <String> visitedHolders = new HashSet<String>();
            
    return parse(strVal, null, visitedHolders, ignoreBadHolders);
        }


        
    private static String parse(String strVal, Map<Object, Object> props,
            Set
    <String> visitedHolders, boolean ignoreBadHolders) throws Exception {

            StringBuffer buf 
    = new StringBuffer(strVal);
            
    int startIndex = strVal.indexOf(DEF_HOLDER_PREFIX);
            
    while (startIndex != -1{
                
    int endIndex = findHolderEndIndex(buf, startIndex);
                
    if (endIndex != -1{
                    String holder 
    = buf.substring(startIndex + DEF_HOLDER_PREFIX_LEN, endIndex);
                    String defValue 
    = null;
                    
    int defIndex = org.apache.commons.lang.StringUtils.lastIndexOf(holder, ":");
                    
    if (defIndex >= 0{
                        defValue 
    = StringUtils.trimWhitespace(holder.substring(defIndex + 1));
                        holder 
    = StringUtils.trimWhitespace(holder.substring(0, defIndex));
                    }


                    
    if (!visitedHolders.add(holder)) {
                        
    throw new Exception("Circular PlaceHolder reference '" + holder
                            
    + "' in property definitions");
                    }

                    
    // Recursive invocation, parsing Holders contained in the Holder key.
                    holder = parse(holder, props, visitedHolders, ignoreBadHolders);
                    
    // Now obtain the value for the fully resolved key
                    String propVal = resolveHolder(holder, props, SYS_PROPS_MODE_FALLBACK, defValue);
                    
    if (propVal != null{
                        
    // Recursive invocation, parsing Holders contained in the
                        
    // previously resolved Holder value.
                        propVal = parse(propVal, props, visitedHolders, ignoreBadHolders);
                        buf.replace(startIndex, endIndex 
    + DEF_HOLDER_SUFFIX_LEN, propVal);
                        startIndex 
    = buf.indexOf(DEF_HOLDER_PREFIX, startIndex + propVal.length());
                    }
     else if (ignoreBadHolders) {
                        
    // Proceed with unprocessed value.
                        startIndex = buf.indexOf(DEF_HOLDER_PREFIX, endIndex + DEF_HOLDER_SUFFIX_LEN);
                    }
     else {
                        
    throw new Exception("Could not resolve Placeholder '" + holder + "'");
                    }

                    visitedHolders.remove(holder);
                }
     else {
                    startIndex 
    = -1;
                }

            }


            
    return buf.toString();
        }


        
    private static int findHolderEndIndex(CharSequence buf, int startIndex) {
            
    int index = startIndex + DEF_HOLDER_PREFIX_LEN;
            
    int withinNestedHolder = 0;
            
    while (index < buf.length()) {
                
    if (StringUtils.substringMatch(buf, index, DEF_HOLDER_SUFFIX)) {
                    
    if (withinNestedHolder > 0{
                        withinNestedHolder
    --;
                        index 
    = index + DEF_HOLDER_SUFFIX_LEN;
                    }
     else {
                        
    return index;
                    }

                }
     else if (StringUtils.substringMatch(buf, index, DEF_HOLDER_PREFIX)) {
                    withinNestedHolder
    ++;
                    index 
    = index + DEF_HOLDER_PREFIX_LEN;
                }
     else {
                    index
    ++;
                }

            }

            
    return -1;
        }


        
    /**
         * Resolve the given Holder using the given properties, performing
         * a system properties check according to the given mode.
         * <p>
         * Default implementation delegates to <code>resolveHolder
         * (Holder, props)</code> before/after the system properties check.
         * <p>
         * Subclasses can override this for custom resolution strategies, including customized points
         * for the system properties check.
         * 
         * 
    @param holder
         *            the Holder to resolve
         * 
    @param props
         *            the merged properties of this configurer
         * 
    @param sysPropsMode
         *            the system properties mode,
         *            according to the constants in this class
         * 
    @return the resolved value, of null if none
         * 
    @see #setSystemPropertiesMode
         * 
    @see System#getProperty
         * 
    @see #resolveHolder(String, java.util.Properties)
         
    */

        
    private static String resolveHolder(String holder, Map<Object, Object> props, int sysPropsMode,
            String defaultValue) 
    {
            String propVal 
    = null;
            
    if (sysPropsMode == SYS_PROPS_MODE_OVERRIDE) {
                propVal 
    = resolveSystemProperty(holder);
            }

            
    if (propVal == null{
                propVal 
    = resolveHolder(holder, props, defaultValue);
            }

            
    if (propVal == null && sysPropsMode == SYS_PROPS_MODE_FALLBACK) {
                propVal 
    = resolveSystemProperty(holder);
            }

            
    return propVal;
        }


        
    /**
         * Resolve the given Holder using the given properties.
         * The default implementation simply checks for a corresponding property key.
         * <p>
         * Subclasses can override this for customized Holder-to-key mappings or custom resolution
         * strategies, possibly just using the given properties as fallback.
         * <p>
         * Note that system properties will still be checked before respectively after this method is
         * invoked, according to the system properties mode.
         * 
         * 
    @param holder
         *            the Holder to resolve
         * 
    @param props
         *            the merged properties of this configurer
         * 
    @return the resolved value, of <code>null</code> if none
         * 
    @see #setSystemPropertiesMode
         
    */

        
    private static String resolveHolder(String holder, Map<Object, Object> props,
            String defaultValue) 
    {
            
    if (props != null{
                Object value 
    = props.get(holder);
                
    if (value != null{
                    
    return "" + value;
                }
     else if (defaultValue != null{
                    
    return defaultValue;
                }

            }


            
    return defaultValue;
        }


        
    /**
         * Resolve the given key as JVM system property, and optionally also as
         * system environment variable if no matching system property has been found.
         * 
         * 
    @param key
         *            the Holder to resolve as system property key
         * 
    @return the system property value, or <code>null</code> if not found
         * 
    @see #setSearchSystemEnvironment
         * 
    @see java.lang.System#getProperty(String)
         * 
    @see java.lang.System#getenv(String)
         
    */

        
    private static String resolveSystemProperty(String key) {
            
    try {
                String value 
    = System.getProperty(key);
                
    if (value == null{
                    value 
    = System.getenv(key);
                }

                
    return value;
            }
     catch (Throwable ex) {
                ex.printStackTrace();
                
    return null;
            }

        }

    }


    下面是測試類:

    import java.util.Properties;

    public class PlaceholderStringTest {
        
    public static void main(String[] args) throws Exception {
            Properties props 
    = new Properties();
            
    // 在.properties文件中放置key1、key2
            props.put("key1""Hello");
            props.put(
    "key2""World");
            
            String str 
    = null;
            
    // 替換key1、key2
            str = PlaceholderUtils.parse("Property:${key1}=${key2}", props);
            System.out.println(str);
    // Property:Hello=World

            
    // 此處要替換的是 key${index:3},先去看.properties屬性中是否有index屬性,有則替換其值
            
    // 再去看系統屬性中是否有index屬性,有則替換其值
            
    // 由于都沒有index屬性,所以取值為 3,也就是要替換 xxx${key3:yyy}
            
    // 由于key3在.properties文件的屬性中、系統屬性中均沒有此屬性,所以返回默認值 yyy
            str = PlaceholderUtils.parse("xxx${key${index:3}:yyy}", props);
            System.out.println(str); 
    // xxxyyy

            
    // 在.properties文件屬性中加入index=2
            props.put("index""2");

            
    // 此處的index屬性值為2,則替換key2的屬性值,默認值yyy被忽略了
            str = PlaceholderUtils.parse("xxx${key${index:3}:yyy}", props);
            System.out.println(str); 
    // xxxWorld

            
    // 系統屬性中加入var1
            System.setProperty("var1""IamSystem");
            str 
    = PlaceholderUtils.parse("xxx${var1}");
            System.out.println(str); 
    // xxxIamSystem

            System.setProperty(
    "var2""System2");
            str 
    = PlaceholderUtils.parse("xxx${var1}.${var2}");
            System.out.println(str);
    // xxxIamSystem.System2

            str 
    = PlaceholderUtils.parse("xxx${var1}.${var3}"true);
            System.out.println(str); 
    // xxxIamSystem.${var3} 
            props.clear();
            
            
    // 模板
            String dburlTmp = "jdbc:oracle:thin:@${host}:${port:1521}:${service_name}";
            Properties dbProps 
    = new Properties();
            dbProps.put(
    "host""localhost");
            dbProps.put(
    "service_name""root");
            str 
    = PlaceholderUtils.parse(dburlTmp, dbProps);
            System.out.println(str); 
    // jdbc:oracle:thin:@localhost:1521:root
        }

    }

    通過上面的代碼,我們便可以實現自己的placeholder了。再加上Json Schema的校驗類,給自己的參數定義Schema,使用時校驗配置參數的正確性,然后再進行Placeholder,最后將這些參數生成Json對象,供程序使用,非常方便。

    本文為原創,歡迎轉載,轉載請注明出處BlogJava

    posted on 2010-09-13 15:44 李 明 閱讀(4914) 評論(2)  編輯  收藏 所屬分類: JavaSpring

    評論

    # re: 順手牽 Spring中的PropertyPlaceholderConfigurer.java 2010-09-13 21:14 cxh8318
    有必要搞得如此復雜嗎?  回復  更多評論
      

    # re: 順手牽 Spring中的PropertyPlaceholderConfigurer.java 2010-09-13 21:43 Java你我
    復雜肯定不是我要的。
    這只是一種解決方法,當然也可以通過增加特殊意義的配置表來完成。@cxh8318
      回復  更多評論
      

    主站蜘蛛池模板: 91成人在线免费观看| 成年免费大片黄在线观看岛国| 亚洲亚洲人成综合网络| 日本免费中文字幕| 亚洲乱码日产精品BD在线观看| 国产伦一区二区三区免费| 中文成人久久久久影院免费观看 | 免费A级毛片无码久久版| 一级有奶水毛片免费看| 亚洲最大视频网站| 亚洲国产精品无码久久青草| 久久国产精品免费视频| 亚洲AV成人精品日韩一区| 亚洲第一福利网站| 日本免费一区二区三区最新| 日本一道本不卡免费| 亚洲精品蜜夜内射| 亚洲国产精品免费视频| 国产成人免费ā片在线观看| 最近中文字幕2019高清免费| 免费的黄色网页在线免费观看| 亚洲黄色在线观看网站| 亚洲午夜无码片在线观看影院猛| 亚洲电影免费观看| 东方aⅴ免费观看久久av| 337P日本欧洲亚洲大胆精品| 亚洲小视频在线观看| 国产成人精品亚洲精品| 四虎影视大全免费入口| 色欲色香天天天综合网站免费| 国产精品亚洲va在线观看| 亚洲国产亚洲片在线观看播放| 久久亚洲综合色一区二区三区| 国产免费资源高清小视频在线观看| 57pao国产成视频免费播放| GOGOGO免费观看国语| 日韩久久无码免费毛片软件| 中文无码亚洲精品字幕| 亚洲国产日韩在线| 亚洲免费精彩视频在线观看| 亚洲精品无码久久久久|