rust实现解析yml配置

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
全局流量管理 GTM,标准版 1个月
简介: rust实现解析yml配置

任何项目都离不开对于配置文件的读取和解析,rust项目也一样。同样的,我们还是需要依赖第三方crate来帮助我们完成针对yml文件的读取和解析工作。

依赖

首先要做的就是引入第三方依赖:

[dependencies]
# 序列化工具
serde = { version = "1.0.140", features = ["derive"] }
serde_json = "1.0.75"
schemars = "0.8.8"
serde_yaml = "0.8.23"
# 初始化工具
lazy_static = "1.4.0"
复制代码

serdeserde_jsonschemars是用来做json序列化操作的;serde_yaml是用来解析yaml字符串的;

lazy_static是用来一次性初始化读取的配置,保持全局都是单例。

创建配置文件

我们在src目录同级创建application.yml和application-dev.yml:

application.yml

profiles:
  active: dev
复制代码

application-dev.yml

# mysql 配置
mysql:
  host: 127.0.0.1
  port: 3306
  username: root
  password: "123456"
  db_name: awesome_db
复制代码

创建配置对应的model

配置文件创建好后,借用面向对象的思想,我们应该要构造与之对应的数据模型,在rust中也就是struct:

use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Profiles {
    pub active: String,
}
// 用来接收application.yml解析结果
#[derive(Serialize, Deserialize, Debug)]
pub struct EnvConfig {
    pub profiles: Profiles,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Mysql {
    pub host: String,
    pub port: u32,
    pub username: String,
    pub password: String,
    pub db_name: String,
}
// 用来接收application-dev.yml解析结果
#[derive(Serialize, Deserialize, Debug)]
pub struct GlobalConfig {
    // 解析对应的mysql配置
    pub mysql: Mysql,
    // 还可以添加其他需要解析的配置
}
复制代码

解析

我们前面已经把配置文件和对应的model都准备好了,下面最关键的就是如何把配置解析成指定的model:

// 加载指定配置文件
fn load_config<T>(path: &str) -> Option<T> where T: DeserializeOwned {
    // 1.通过std::fs读取配置文件内容
    // 2.通过serde_yaml解析读取到的yaml配置转换成json对象
    match serde_yaml::from_str::<RootSchema>(&std::fs::read_to_string(path).expect(&format!("failure read file {}", path))) {
        Ok(root_schema) => {
            // 通过serde_json把json对象转换指定的model
            let data = serde_json::to_string_pretty(&root_schema).expect("failure to parse RootSchema");
            let config = serde_json::from_str::<T>(&*data).expect(&format!("failure to format json str {}",&data));
            // 返回格式化结果
            Some(config)
        }
        Err(err) => {
            // 记录日志
            info!("{}",err);
            // 返回None
            None
        }
    }
}
复制代码

上面是一个抽象化的方法,也是最核心的方法。需要注意的是泛型对象得是DeserializeOwned,而不是Deserialize<'a>,原因在于serde_json::from_str::<T>()所需要的参数是一个有生命周期的参数,但是data在方法执行完毕后会被销毁掉,但是返回值并不是马上销毁,它还需要给外面的调用中使用,所以导致Deserialize<'a>解决不了问题,一直无法通过编译。DeserializeOwned就可以解决这种问题。

// 加载目标文件application.yml
fn load_env_config() -> Option<EnvConfig> {
    load_config::<EnvConfig>("application.yml")
}
// 根据环境加载application-{}.yml文件
fn load_global_config_from_env(active: String) -> Option<GlobalConfig> {
    let path = format!("application-{}.yml", active);
    load_config::<GlobalConfig>(&path)
}
// 真正对外暴露的方法,根据application.yml指定的环境变量动态加载对应的配置文件
pub fn load_global_config() -> Option<GlobalConfig> {
    if let Some(env_config) = load_env_config() {
        return load_global_config_from_env(env_config.profiles.active);
    }
    None
}
复制代码

测试

为了测试我们的代码是否能正常运行,我们编写一些简单的测试用例:

#[cfg(test)]
mod test {
    use crate::load_config::init_load_config::load_global_config;
    use crate::load_config::models::GlobalConfig;
    #[test]
    pub fn load_config_test() {
        match load_global_config() {
            None => {
                println!("None");
            }
            Some(config) => {
                println!("{:#?}", config);
            }
        }
    }
}
复制代码

输出结果如下:

Finished test [unoptimized + debuginfo] target(s) in 1.08s
Running unittests src/main.rs (target/debug/deps/hello_salvo-b9ecf8dc1aa86991)
GlobalConfig {
    mysql: Mysql {
        host: "127.0.0.1",
        port: 3306,
        username: "root",
        password: "123456",
        db_name: "awesome_db",
    },
}
复制代码

单例化

为了能在项目中使用咱们上面已经实现的全局配置参数,我们需要对它做一次初始化操作。也就是在整个项目中,只加载一次该配置:

use lazy_static::lazy_static;
use crate::load_config::init_load_config;
use crate::load_config::models::GlobalConfig;
lazy_static! {
    pub static ref GLOBAL_CONFIG:GlobalConfig=init_load_config::load_global_config().unwrap();
}
复制代码

通过lazy_static的宏来控制配置文件一次性载入后,在项目中只需要直接使用即可。

main函数使用

fn main() {
    let config = &GLOBAL_CONFIG;
    println!("{:?}", config.mysql);
}
复制代码

在main函数中,可以直接使用已经初始化成功后的GLOBAL_CONFIG了。

至此,我们使用rust解析yml配置文件就完成了。


相关文章
|
2月前
|
Prometheus 监控 关系型数据库
数据库同步革命:MySQL GTID模式下主从配置的全面解析
数据库同步革命:MySQL GTID模式下主从配置的全面解析
204 0
|
6天前
|
安全 Java 数据库连接
后端框架的学习----mybatis框架(3、配置解析)
这篇文章详细介绍了MyBatis框架的核心配置文件解析,包括环境配置、属性配置、类型别名设置、映射器注册以及SqlSessionFactory和SqlSession的生命周期和作用域管理。
后端框架的学习----mybatis框架(3、配置解析)
|
5天前
|
负载均衡 网络协议 应用服务中间件
如何配置 DNS 轮询负载均衡以实现高可用性
如何配置 DNS 轮询负载均衡以实现高可用性
16 4
|
17天前
|
XML Android开发 UED
"掌握安卓开发新境界:深度解析AndroidManifest.xml中的Intent-filter配置,让你的App轻松响应scheme_url,开启无限交互可能!"
【8月更文挑战第2天】在安卓开发中,scheme_url 通过在`AndroidManifest.xml`中配置`Intent-filter`,使应用能响应特定URL启动或执行操作。基本配置下,应用可通过定义特定URL模式的`Intent-filter`响应相应链接。
46 12
|
23天前
|
缓存 负载均衡 应用服务中间件
nginx.conf 配置解析及常用配置
nginx.conf 配置解析及常用配置
54 6
|
22天前
|
弹性计算 缓存 前端开发
阿里云服务器配置选择指南2核4G、4核8G和8核16G性能全解析!
阿里云2核4G、4核8G与8核16G服务器配置解析及选择指南。根据不同业务需求,推荐ECS经济型e、通用算力型u1、计算型c7/c8i实例。企业用户专享2核4G ECS u1实例仅199元/年,自带5M带宽;4核8G u1实例起价955.58元/年;8核16G c7实例起价6544元/年。各实例CPU性能各异,如c7采用第三代Intel Xeon处理器,适配高性能计算场景。
70 10
|
4天前
|
安全 Nacos 数据库
【技术安全大揭秘】Nacos暴露公网后被非法访问?!6大安全加固秘籍,手把手教你如何保护数据库免遭恶意篡改,打造坚不可摧的微服务注册与配置中心!从限制公网访问到启用访问控制,全方位解析如何构建安全防护体系,让您从此告别数据安全风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其公网暴露可能引发数据库被非法访问甚至篡改的安全隐患。本文剖析此问题并提供解决方案,包括限制公网访问、启用HTTPS、加强数据库安全、配置访问控制及监控等,帮助开发者确保服务安全稳定运行。
12 0
|
4天前
|
安全 Nacos 数据安全/隐私保护
【技术干货】破解Nacos安全隐患:连接用户名与密码明文传输!掌握HTTPS、JWT与OAuth2.0加密秘籍,打造坚不可摧的微服务注册与配置中心!从原理到实践,全方位解析如何构建安全防护体系,让您从此告别数据泄露风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其连接用户名和密码的明文传输成为安全隐患。本文探讨加密策略提升安全性。首先介绍明文传输风险,随后对比三种加密方案:HTTPS简化数据保护;JWT令牌减少凭证传输,适配分布式环境;OAuth2.0增强安全,支持多授权模式。每种方案各有千秋,开发者需根据具体需求选择最佳实践,确保服务安全稳定运行。
19 0
|
10天前
|
安全 关系型数据库 MySQL
"深度解析:MySQL密码修改与远程登录配置全攻略,保障数据库安全与灵活访问"
【8月更文挑战第9天】MySQL是广受青睐的开源关系型数据库系统,其安全性和易用性对DBA和开发者至关重要。本文通过实例解析MySQL中用户密码更新及远程登录配置,确保数据库安全访问与高效管理。首先介绍如何分步修改密码,包括登录MySQL、选择数据库、使用`ALTER USER`命令更新密码,并刷新权限。接着,指导如何配置远程访问,涉及调整MySQL监听地址、授权用户远程登录、检查网络设置及测试远程连接。遵循这些步骤,可强化数据库安全性并实现灵活管理。
46 0
|
2月前
|
存储 缓存 运维
云计算中的服务器选型与配置:技术深度解析
【6月更文挑战第29天】云计算服务器选型与配置深度解析:关注业务需求、技术要求及成本效益。重点包括CPU、内存、存储和网络配置的优化,结合负载均衡、缓存、虚拟化和自动化运维策略,以提升性能和效率,确保云服务的稳定与高效。

推荐镜像

更多