rust-config配置读取
config用法
# 添加config库
cargo add config
cargo add serde --features derive
嵌套结构
test.toml配置文件
debug = false
fruits = ["apple", "banana", "cherry"]
[server]
[server.test]
host = "localhost"
port = 8080
[server.dev]
host = "localhost"
port = 8081
[database]
[database.test]
url = "postgres://localhost/mydb"
port = 15432
[database.dev]
url = "postgres://localhost/mydb"
port = 5432
test.json配置文件
{
"debug": false,
"fruits": ["apple", "banana", "cherry"],
"server": {
"test": {
"host": "localhost",
"port": 8080
},
"dev": {
"host": "localhost",
"port": 8081
}
},
"database": {
"test": {
"url": "postgres://localhost/mydb",
"port": 15432
},
"dev": {
"url": "postgres://localhost/mydb",
"port": 5432
}
}
}
读取配置文件
File::with_name()可以使用Path
use config::{Config, File};
use serde::Deserialize;
// server配置
#[derive(Debug, Deserialize)]
struct Server {
test: ServerConfig,
dev: ServerConfig,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u32,
}
// db配置
#[derive(Debug, Deserialize)]
struct Database {
test: DatabaseConfig,
dev: DatabaseConfig,
}
#[derive(Debug, Deserialize)]
struct DatabaseConfig {
url: String,
port: u32,
}
#[derive(Debug, Deserialize)]
struct Settings {
debug: bool,
fruits: Vec<String>,
server: Server,
database: Database,
}
fn main() -> Result<(), config::ConfigError> {
let settings = Config::builder()
.add_source(File::with_name("config/test"))
.build()?
.try_deserialize::<Settings>()?;
println!("{:#?}", settings);
Ok(())
}
Settings {
debug: false,
fruits: [
"apple",
"banana",
"cherry",
],
server: Server {
test: ServerConfig {
host: "localhost",
port: 8080,
},
dev: ServerConfig {
host: "localhost",
port: 8081,
},
},
database: Database {
test: DatabaseConfig {
url: "postgres://localhost/mydb",
port: 15432,
},
dev: DatabaseConfig {
url: "postgres://localhost/mydb",
port: 5432,
},
},
}
Config::builder()用法
Config加载顺序
- 整体
- set_default(...) 最先加载
- add_source(...) 中间按添加顺序覆盖
- set_override(...) 最后加载,优先级最高
- 多个相同的
- 多个 add_source(...) 之间,顺序重要
- 多个 set_default(...) 之间,如果设置同一路径,后面的会覆盖前面的
- 多个 set_override(...) 之间,如果设置同一路径,后面的会覆盖前面的
let settings = Config::builder()
.set_default("debug", false)?
.add_source(File::with_name("config/default"))
.add_source(File::with_name("config/development").required(false))
.add_source(Environment::with_prefix("MYAPP").prefix_separator("_").separator("__"))
.set_override("server.dev.port", 3000)?
.build()?
.try_deserialize::<Settings>()?;
默认值 < default.toml < development.toml < 环境变量 < set_override
设置默认值set_default
use config::Config;
use serde::Deserialize;
// server配置
#[derive(Debug, Deserialize)]
struct Server {
test: ServerConfig,
dev: ServerConfig,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u32,
}
#[derive(Debug, Deserialize)]
struct Settings {
debug: bool,
server: Server
}
fn main() -> Result<(), config::ConfigError> {
let settings = Config::builder()
// 设置默认值
.set_default("debug", true)?
.set_default("server.test.host", "127.0.0.1")?
.set_default("server.test.port", 8080)?
.set_default("server.dev.host", "0.0.0.0")?
.set_default("server.dev.port", 9000)?
.build()?
.try_deserialize::<Settings>()?; // 转为结构体
println!("{:#?}", settings);
Ok(())
}
Settings {
debug: true,
server: Server {
test: ServerConfig {
host: "127.0.0.1",
port: 8080,
},
dev: ServerConfig {
host: "0.0.0.0",
port: 9000,
},
},
}
加载配置add_source
配置文件导入
如果有相同配置,后面的导入会覆盖前面导入
File::with_name("config/server")- 表示读取
config/server.toml、config/server.json、config/server.yaml等配置文件 - 不需要手写扩展名,
config这个库会根据支持的格式自动匹配
- 表示读取
[server]
[server.dev]
host = "11.11.11.11"
port = 80
// 导入File
use config::{Config, File};
use serde::Deserialize;
// server配置
#[derive(Debug, Deserialize)]
struct Server {
test: ServerConfig,
dev: ServerConfig,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u32,
}
#[derive(Debug, Deserialize)]
struct Settings {
debug: bool,
server: Server,
}
fn main() -> Result<(), config::ConfigError> {
let settings = Config::builder()
.set_default("debug", true)?
.set_default("server.test.host", "127.0.0.1")?
.set_default("server.test.port", 8080)?
.set_default("server.dev.host", "0.0.0.0")?
.set_default("server.dev.port", 9000)?
// 从配置文件导入
.add_source(File::with_name("config/server").required(false))
.build()?
.try_deserialize::<Settings>()?; // 转为结构体
println!("{:#?}", settings);
Ok(())
}
Settings {
debug: true,
server: Server {
test: ServerConfig {
host: "127.0.0.1",
port: 8080,
},
dev: ServerConfig {
host: "11.11.11.11",
port: 80,
},
},
}
读取多个配置文件
.required(false)表示配置文件不存在也不会报错,适合可选配置文件,例如本地开发配置、环境专用配置。
config/
default.toml
development.toml
let settings = Config::builder()
.add_source(File::with_name("config/default"))
.add_source(File::with_name("config/development").required(false))
.build()?
.try_deserialize::<Settings>()?;
环境变量获取
⚠️如果不显式设置
prefix_separator("_"),那么prefix和字段之间默认也会使用separator("__")。
-
prefix_separator决定 MYAPP 和后面配置名之间怎么分开 -
separator决定后面配置名内部的嵌套层级怎么分开 -
Environment::with_prefix("MYAPP").separator("__")- MYAPP__SERVER__DEV__PORT
MYAPP__表示“这是我的应用配置”SERVER__DEV__PORT表示嵌套字段server.dev.port
- MYAPP__SERVER__DEV__PORT
-
Environment::with_prefix("MYAPP").prefix_separator("_").separator("__")- MYAPP_SERVER__DEV__PORT
MYAPP_表示“这是我的应用配置”SERVER__DEV__PORT表示嵌套字段server.dev.port
- MYAPP_SERVER__DEV__PORT
use config::{Config, Environment, File};
use serde::Deserialize;
// server配置
#[derive(Debug, Deserialize)]
struct Server {
test: ServerConfig,
dev: ServerConfig,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u32,
}
#[derive(Debug, Deserialize)]
struct Settings {
debug: bool,
server: Server,
}
fn main() -> Result<(), config::ConfigError> {
let settings = Config::builder()
.set_default("debug", true)?
.set_default("server.test.host", "127.0.0.1")?
.set_default("server.test.port", 8080)?
.set_default("server.dev.host", "0.0.0.0")?
.set_default("server.dev.port", 9000)?
.add_source(File::with_name("config/server").required(false))
.add_source(Environment::with_prefix("MYAPP").prefix_separator("_").separator("__"))
.build()?
.try_deserialize::<Settings>()?; // 转为结构体
println!("{:#?}", settings);
Ok(())
}
MYAPP_SERVER__DEV__PORT=2000 cargo run
Settings {
debug: true,
server: Server {
test: ServerConfig {
host: "127.0.0.1",
port: 8080,
},
dev: ServerConfig {
host: "11.11.11.11",
port: 2000,
},
},
}
set_override
代码里最后拍板,优先级最高
- 用于
myapp run --port 3000直接覆盖
use config::{Config, Environment, File};
use serde::Deserialize;
// server配置
#[derive(Debug, Deserialize)]
struct Server {
test: ServerConfig,
dev: ServerConfig,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u32,
}
#[derive(Debug, Deserialize)]
struct Settings {
debug: bool,
server: Server,
}
fn main() -> Result<(), config::ConfigError> {
let mut config_build = Config::builder()
.set_default("debug", true)?
.set_default("server.test.host", "127.0.0.1")?
.set_default("server.test.port", 8080)?
.set_default("server.dev.host", "0.0.0.0")?
.set_default("server.dev.port", 9000)?
.add_source(File::with_name("config/server").required(false))
.add_source(Environment::with_prefix("MYAPP").prefix_separator("_").separator("__"));
// 添加识别--port
let args: Vec<String> = std::env::args().collect();
let mut i = 0;
while i < args.len() {
if args[i] == "--port" && i + 1 < args.len() {
if let Ok(port) = args[i + 1].parse::<u32>() {
config_build= config_build.set_override("server.dev.port", port)?;
}
i += 1;
}
i += 1;
}
let settings = config_build
.build()?
.try_deserialize::<Settings>()?; // 转为结构题
println!("{:#?}", settings);
Ok(())
}
cargo run -- --port 1234
Settings {
debug: true,
server: Server {
test: ServerConfig {
host: "127.0.0.1",
port: 8080,
},
dev: ServerConfig {
host: "11.11.11.11",
port: 1234,
},
},
}

浙公网安备 33010602011771号