Spark笔记(5):scala两种配置参数的方法

spark


很多时候我们需要把一些参数保存在文件里,等程序运行时动态加载,分享两种scala调用的方式:1.Typesafe的Config库 2.java.util.Properties类简单介绍其一些用法

1.Typesafe的Config库

纯Java写成、零外部依赖、代码精简、功能灵活、API友好。支持Java properties、JSON、JSON超集格式HOCON以及环境变量。它也是Akka的配置管理库。

maven依赖

<!-- https://mvnrepository.com/artifact/com.typesafe/config -->
    <dependency>
      <groupId>com.typesafe</groupId>
      <artifactId>config</artifactId>
      <version>1.4.0</version>
    </dependency>

概述

  • 纯java实现,无任何依赖
  • 充分的测试
  • 支持: Java properties, JSON, and a human-friendly JSON superset
  • 可以合并各种格式的配置文件
  • 可以通过文件、urls、classpath加载配置
  • 支持多层嵌套的配置方式
  • 识别Java system properties, 如java -Dmyapp.foo.bar=10
  • 可以转换长短,大小等单位。如配置文件中timeout=10s,则可以转换成任意的毫秒或者
  • 类型转换,比如yes可以转换为boolean类型的true

默认加载classpath下的application.conf,application.json和application.properties文件。通过ConfigFactory.load()加载。

java实现方式
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

public class CommonConfig {

    private Config config;

    //指定配置文件
    public CommonConfig(Config config) {
        this.config = config;
        config.checkValid(ConfigFactory.defaultReference(), "simple-lib");
    }

    // 默认加载classpath下的application.*
    public CommonConfig() {
        this(ConfigFactory.load());
    }

    //打印
    public void printSetting(String path) {
        System.out.println("The setting '" + path + "' is: " + config.getString(path));
    }

    public static void main(String[] args) {
        CommonConfig s = new CommonConfig();
        s.printSetting("simple-app.answer");
    }
}
scala实现方式
1.工具类
package com.suning.sospdm.utils

import java.io.FileNotFoundException
import java.util

import com.typesafe.config.{Config, ConfigFactory}
import org.apache.commons.collections.CollectionUtils
import org.apache.commons.lang3.{ArrayUtils, StringUtils}

/**
  * Description: 
  * Author: 18051165 WuYu 
  * Date: 2019/12/30 14:58
  */
object ConfigLoader {
  private var config:Config = _
  private val PROFILES_ACTIVE_KEY = "app.profiles.active"

  /**
    * 获取配置信息
    * @return Config对象
    */
  def getConfig:Config = {
    if (config == null || config.isEmpty) {
      // 默认方式
      var cfg = ConfigFactory.load()
      // 配置处理
      if(cfg.hasPath(PROFILES_ACTIVE_KEY)){
        val activeProfiles = cfg.getAnyRef(PROFILES_ACTIVE_KEY)
        activeProfiles match {
          case file: String =>
            if (!StringUtils.isEmpty(file)) {
              try {
                cfg = ConfigFactory.load(file)
              } catch {
                case e: FileNotFoundException => println(e.getMessage)
              }
            }
          case files: util.List[String] =>
            if (!CollectionUtils.isEmpty(files)) {
              val itr = files.iterator()
              while (itr.hasNext) {
                try {
                  val f = itr.next()
                  val tmpConfig = ConfigFactory.load(f)
                  cfg = cfg.withFallback(tmpConfig)
                } catch {
                  case e: FileNotFoundException => println(e.getMessage)
                }
              }
            }
          case _ =>
        }
      }
      cfg
    } else {
      config
    }
  }

  /**
    * 刷新config
    * @return Unit
    */
  def refresh():Unit = {config = ConfigFactory.load()}
}

ConfigFactory.load()会加载配置文件,默认加载classpath下的application.conf,application.jsonapplication.properties文件。
也可以调用ConfigFactory.load(confFileName)加载指定的配置文件。

2.application.json文件
{
  "app": {
    "profiles":{
      "active": ["./config/dev0.json","./config/dev1.json"]
    },
    "name": "template",
    "master": "local",
    "spark": {
      "config": {
        "testing": {
          "memory": "512000000"
        },
        "hive": {
          "enable": false
        }
      }
    },
    "resources":{
      "data": "E:\\Spark\\myAlgorithmDemo\\src\\main\\resources\\data\\iris.data",
      "model": "E:\\Spark\\myAlgorithmDemo\\src\\main\\resources\\model"
    }
  }
}
3.实例
package com.suning.sospdm.utils

import com.suning.sospdm.utils.ConfigLoader
import com.typesafe.config.Config

/**
  * Description: 
  * Author: 18051165 WuYu 
  * Date: 2019/12/30 15:27
  */
object ConfigTest {
  def main(args: Array[String]): Unit = {
    val c = ConfigLoader.getConfig
    // 默认地址读取配置
    printConfig("app.name", c)
    printConfig("app.resources.data", c)
    // 指定地址读取
    printConfig("app.test0", c)
    printConfig("app.test1", c)
  }

  def printConfig(configName:String, c:Config): Unit = {
    println("The setting " + configName + " is: " + c.getString(configName))
  }
}

结果如下,在dev0dev1中可以实现相同key,不同value的调用,方便不同环境使用不同的参数,而不用修改其他代码

The setting app.name is: config test
The setting app.resources.data is: E:\Spark\myAlgorithmDemo\src\main\resources\data\iris.data
The setting app.test0 is: this is dev0 config
The setting app.test1 is: this is dev1 config

2.java.util.Properties

Properties是一个键值对存储容器,且键和值的类型都是String,其中键不会重复,文件中后面的会覆盖前面的同名键值对。

*.properties例子
spark.enableHiveSupport = false
spark.memory = 512000000
dataPath = E:/Spark/myAlgorithmDemo/src/main/resources/data
modelPath = E:/Spark/myAlgorithmDemo/src/main/resources/model
scala实现
1.工具类
package com.suning.sospdm.utils

import java.io.InputStream
import java.util.Properties

import org.slf4j.{Logger, LoggerFactory}

/**
  * Description: 参数配置
  * Author: 18051165 WuYu 
  * Date: 2019/11/10 15:01
  */
object PropertyUtils extends Serializable {
  val log: Logger = LoggerFactory.getLogger(this.getClass)
  var p: Properties = _

  def apply(): Properties = {
    p = new Properties
    val fileNames = PropertyFileNameEnum.values
    for (fileName <- fileNames) {
      loadProperties(fileName.toString)
    }
    p
  }

  def loadProperties(fileName: String): Unit = {
    var is: InputStream = null
    try {
      is = this.getClass.getResourceAsStream(fileName)
      p.load(is)
    } catch {
      case e: Exception =>
        throw new RuntimeException(e)
    } finally {
      if (null != is)
        try
          is.close()
        catch {
          case e: Exception => throw new RuntimeException(e)
        }
    }
  }

  private[utils] object PropertyFileNameEnum extends Enumeration {
    type PropertyFileNameEnum = Value
    val SPARK: PropertyUtils.PropertyFileNameEnum.Value = Value("/spark.properties")
  }
}

默认情况下可以直接读取resources下*.properties文件,在pom文件中配置maven工具可以设置不同环境,在打包的过程中可以分配配置不同环境下的参数,方便实际工程应用

2.pom文件配置
  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <excludes>
          <exclude>dev/*</exclude>
          <exclude>pre/*</exclude>
          <exclude>prd/*</exclude>
          <exclude>*.properties</exclude>
        </excludes>
      </resource>
      <resource>
        <directory>src/main/resources/${profiles.active}</directory>
      </resource>
    </resources>
  </build>
  <!-- 打包命令:clean compile install assembly:assembly -P pre -->
  <profiles>
    <profile>
      <id>dev</id>
      <properties>
        <!-- 默认本地环境 -->
        <profiles.active>dev</profiles.active>
      </properties>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
    </profile>
    <profile>
      <id>pre</id>
      <properties>
        <!-- 其他环境 pre -->
        <profiles.active>pre</profiles.active>
      </properties>
    </profile>
    <profile>
      <id>prd</id>
      <properties>
        <!-- 其他环境 生产环境prd -->
        <profiles.active>prd</profiles.active>
      </properties>
    </profile>
  </profiles>

pom文件配置好后,IDEA的Maven工具就会如下显示:

IDEA显示截图
3.实例
package com.suning.sospdm.utils

import java.util.Properties
import com.suning.sospdm.utils.PropertyUtils

/**
  * Description: 
  * Author: 18051165 WuYu 
  * Date: 2019/12/30 16:34
  */
object PropertyTest {
  val prop: Properties = PropertyUtils()
  
  def main(args: Array[String]): Unit = {
    printConfig("profiles", prop)
    printConfig("spark.enableHiveSupport", prop)
    printConfig("spark.memory", prop)
  }

  def printConfig(propertyName:String, p:Properties): Unit = {
    println("The setting " + propertyName + " is: " + p.getProperty(propertyName))
  }
}

Maven Profiles默认dev环境的结果:

The setting profiles is: dev
The setting spark.enableHiveSupport is: false
The setting spark.memory is: 512000000

Maven Profiles选择prd环境的结果:

The setting profiles is: prd
The setting spark.enableHiveSupport is: true
The setting spark.memory is: 2048000000
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352