美文网首页大数据 爬虫Python AI Sql玩转大数据大数据-简书
《Hadoop技术内幕深入解析Hadoop和HDFS》2.2.4

《Hadoop技术内幕深入解析Hadoop和HDFS》2.2.4

作者: 程序员1 | 来源:发表于2018-09-28 13:57 被阅读5次

    2.2.4 使用 get* 和 set* 访问 / 设置配置项

    1. get*

    get* 一共代表 21 个方法,它们用于在 Configuration 对象中获取相应的配置信息。这

    些配置信息可以是 boolean(getBoolean)、int(getInt)、long(getLong)等基本类型,也

    可以是其他一些 Hadoop 常用类型,如类的信息(getClassByName、getClasses、getClass)、

    String 数 组(getStringCollection、getStrings)、URL(getResource) 等。 这 些 方 法 里 最

    重要的是 get() 方法,它根据配置项的键获取对应的值,如果键不存在,则返回默认值

    defaultValue。其他的方法都会依赖于 Configuration.get(),并在 get() 的基础上做进一步处

    理。get() 方法如下:

    public String get(String name, String defaultValue)

    Configuration.get() 会调用 Configuration 的私有方法 substituteVars(),该方法会完成配置

    的属性扩展。属性扩展是指配置项的值包含 ${key} 这种格式的变量,这些变量会被自动替

    换成相应的值。也就是说,${key} 会被替换成以 key 为键的配置项的值。注意,如果 ${key}

    替换后,得到的配置项值仍然包含变量,这个过程会继续进行,直到替换后的值中不再出现

    变量为止。

    substituteVars 的工作依赖于正则表达式:

    varPat:\$\{[^\}\$ ]+\}

    由于“$”、左花括号“{”、右花括号“}”都是正则表达式中的保留字,因此需要通过

    “\”进行转义。正则表达式 varPat 中,“\$\{”部分用于匹配 ${key} 中的 key 前面的“${”,

    最后的“\}”部分匹配属性扩展项的右花括号“}”,中间部分“[^\}\$ ]+”用于匹配属性扩展

    键,它使用了两个正则表达式规则:

    [^ ] 规则,通过 [^ ] 包含一系列的字符,使表达式匹配这一系列字符以外的任意一个 ❑

    字符。也就是说,“[^\}\$ ]”将匹配除了“}”、“$”和空格以外的所有字符。注意,

    $ 后面还包含了一个空格,这个看不见的空格,是通过空格的 Unicode 字符 \u0020 添

    加到表达式中的。

    + 是一个修饰匹配次数的特殊符号,通过该符号保证了“+”前面的表达式“[^\}\$ ]” ❑

    至少出现 1 次。

    通过正则表达式“\$\{[^\}\$ ]+\}”,可以在输入字符串里找出需要进行属性扩展的地方,

    并通过字符串替换,进行属性扩展。

    前面提过,如果一次属性扩展完成以后,得到的表达式里仍然包含可扩展的变量,那

    么,substituteVars() 需要再次进行属性扩展。考虑下面的情况:

    属性扩展 ${key1} 的结果包含属性扩展 ${key2},而对 ${key2} 进行属性扩展后,产生

    了一个包含 ${key1} 的新结果,这会导致属性扩展进入死循环,没办法停止。

    针对这种可能发生的情况,substituteVars() 中使用了一个非常简单而又有效的策略,即

    属性扩展只能进行一定的次数(20 次,通过 Configuration 的静态成员变量 MAX_SUBST 定

    义),避免出现上面分析的属性扩展死循环。

    最后一点需要注意的是,substituteVars() 中进行的属性扩展,不但可以使用保存在

    Configuration 对象中的键 – 值对,而且还可以使用 Java 虚拟机的系统属性。如系统属

    性 user.home 包含了当前用户的主目录,如果用户有一个配置项需要使用这个信息,可

    以通过属性扩展 ${user.home},来获得对应的系统属性值。而且,Java 命令行可以通过

    “-D=”的方式定义系统属性。这就提供了一个通过命令行,覆盖或者设置

    Hadoop 运行时配置信息的方法。在 substituteVars() 中,属性扩展优先使用系统属性,然后

    才是 Configuration 对象中保存的键 – 值对。具体代码如下:

    // 正则表达式对象,包含正则表达式 \$\{[^\}\$ ]+\}

    // 注意,u0020 前面只有一个”\”,转义发生在 Java 里,不在正则表达式里

    private static Pattern varPat =

    Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");

    // 最多做 20 次属性扩展

    private static int MAX_SUBST = 20;

    private String substituteVars(String expr) {

    if (expr == null) {

    return null;

    }

    Matcher match = varPat.matcher("");

    String eval = expr;

    // 循环,最多做 MAX_SUBST 次属性扩展

    for(int s=0; s

    match.reset(eval);

    if (!match.find()) {

    return eval; // 什么都没有找到,返回

    }

    String var = match.group();

    var = var.substring(2, var.length()-1); // 获得属性扩展的键

    String val = null;

    try {

    // 看看系统属性里有没有 var 对应的 val

    // 这一步保证了我们首先使用系统属性做属性扩展

    val = System.getProperty(var);

    } catch(SecurityException se) {

    LOG.warn("Unexpected SecurityException in Configuration", se);

    }

    if (val == null) {

    // 看看 Configuration 保存的键 - 值对里有没有 var 对应的 val

    val = getRaw(var);

    }

    if (val == null) {

    // 属性扩展中的 var 没有绑定,不做扩展,返回

    return eval;

    }

    // 替换 ${……},完成属性扩展

    eval = eval.substring(0,match.start())

    +val+eval.substring(match.end());

    }

    // 属性扩展次数过多,抛异常

    throw new IllegalStateException(……);

    }

    2. set*

    相对于 get* 来说,set* 的大多数方法都很简单,这些方法对输入进行类型转换等处理后,

    最终都调用了下面的 Configuration.set() 方法:

    public String set(String name, String value)

    对 比 相 对 复 杂 的 Configuration.get(), 成 员 函 数 set() 只 是 简 单 地 调 用 了 成 员 变 量

    properties 和 overlay 的 setProperty() 方法,保存传入的键 – 值对。

    相关文章

      网友评论

        本文标题:《Hadoop技术内幕深入解析Hadoop和HDFS》2.2.4

        本文链接:https://www.haomeiwen.com/subject/ndqpoftx.html