Skip to content

Commit 669b3b0

Browse files
committed
feat(config): 实现环境变量文件动态加载机制
- 在Web API和CLI入口点引入环境变量文件加载逻辑 - 支持通过ENV_FILE环境变量指定配置文件路径 - 添加默认配置文件创建功能,当配置文件不存在时自动生成 - 更新日志记录方式,在加载失败时输出错误信息 - 移除旧的静态环境变量加载方法 - 添加标准配置项注释,提高可读性和维护性
1 parent dc45405 commit 669b3b0

4 files changed

Lines changed: 135 additions & 5 deletions

File tree

.file_classification_env

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# File Classification 系统配置文件
2+
# 数据库配置
3+
DATABASE_URL=file_classification.db
4+
DATABASE_TYPE=sqlite
5+
6+
# Web API 配置
7+
BIND_ADDRESS=127.0.0.1
8+
BIND_PORT=8082
9+
10+
# 日志配置
11+
RUST_LOG=info
12+
RUST_LOG_FILE=debug
13+
14+
# CORS 配置
15+
CORS_ENABLED=true
16+
CORS_ORIGIN=http://localhost:8082

file_classification_cli/src/main.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// 主入口文件,负责解析CLI参数并分派到相应处理函数
33

44
use std::error::Error;
5+
use std::env;
6+
use std::fs;
7+
use std::path::Path;
58

69
use clap::Parser;
710

@@ -19,12 +22,67 @@ mod interactive;
1922
mod parsers;
2023
mod repl;
2124

25+
/// 加载环境变量文件
26+
///
27+
/// 加载顺序:
28+
/// 1. 通过 ENV_FILE 环境变量指定的文件
29+
/// 2. 回退到 .file_classification_env
30+
/// 3. 如果以上都不存在,则创建带有默认配置的 .file_classification_env
31+
fn load_env_file() -> Result<Option<String>, Box<dyn std::error::Error>> {
32+
// 首先检查是否通过环境变量指定了env文件
33+
let env_file = env::var("ENV_FILE").unwrap_or_else(|_| ".file_classification_env".to_string());
34+
35+
// 尝试加载指定的env文件
36+
if Path::new(&env_file).exists() {
37+
dotenvy::dotenv_override().ok();
38+
dotenvy::from_filename_override(&env_file)?;
39+
Ok(Some(env_file))
40+
} else if env_file != ".file_classification_env" && Path::new(".file_classification_env").exists() {
41+
// 如果指定了自定义env文件但不存在,回退到.file_classification_env
42+
dotenvy::dotenv_override().ok();
43+
dotenvy::from_filename_override(".file_classification_env")?;
44+
Ok(Some(".file_classification_env".to_string()))
45+
} else {
46+
// 如果文件都不存在,创建默认的.file_classification_env
47+
create_default_env_file()?;
48+
dotenvy::dotenv_override().ok();
49+
dotenvy::from_filename_override(".file_classification_env")?;
50+
Ok(None)
51+
}
52+
}
53+
54+
/// 创建默认的环境变量配置文件
55+
fn create_default_env_file() -> Result<(), Box<dyn std::error::Error>> {
56+
let default_content = r#"# File Classification 系统配置文件
57+
# 数据库配置
58+
DATABASE_URL=file_classification.db
59+
DATABASE_TYPE=sqlite
60+
61+
# Web API 配置
62+
BIND_ADDRESS=127.0.0.1
63+
BIND_PORT=8082
64+
65+
# 日志配置
66+
RUST_LOG=info
67+
RUST_LOG_FILE=debug
68+
69+
# CORS 配置
70+
CORS_ENABLED=true
71+
CORS_ORIGIN=http://localhost:8082
72+
"#;
73+
74+
fs::write(".file_classification_env", default_content)?;
75+
Ok(())
76+
}
77+
2278
/// 主函数:解析命令行参数,初始化数据库连接和上下文,并处理命令
2379
fn main() -> Result<(), Box<dyn Error>> {
2480
let cli = Cli::parse();
2581

26-
// 加载 .env 文件中的环境变量
27-
dotenvy::dotenv().ok();
82+
// 加载环境变量文件
83+
if let Err(e) = load_env_file() {
84+
eprintln!("加载环境变量文件失败: {}", e);
85+
}
2886

2987
// 从环境变量中获取数据库连接URL和数据库类型
3088
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");

file_classification_webapi/src/bin/file_classification_webapi.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use actix_files as fs;
21
use actix_web::{middleware::Logger, web, App, HttpResponse, HttpServer, Result};
32
mod handlers;
43
mod utils;
@@ -7,6 +6,8 @@ use actix_cors::Cors;
76
use actix_files::NamedFile;
87
use log;
98
use std::env;
9+
use std::fs;
10+
use std::path::Path;
1011
use std::path::PathBuf;
1112

1213
// 引入数据库连接相关类型
@@ -35,6 +36,59 @@ async fn static_handler(path: web::Path<String>) -> Result<NamedFile> {
3536
Ok(NamedFile::open(full_path)?)
3637
}
3738

39+
/// 加载环境变量文件
40+
///
41+
/// 加载顺序:
42+
/// 1. 通过 ENV_FILE 环境变量指定的文件
43+
/// 2. 回退到 .file_classification_env
44+
/// 3. 如果以上都不存在,则创建带有默认配置的 .file_classification_env
45+
fn load_env_file() -> Result<Option<String>, Box<dyn std::error::Error>> {
46+
// 首先检查是否通过环境变量指定了env文件
47+
let env_file = env::var("ENV_FILE").unwrap_or_else(|_| ".file_classification_env".to_string());
48+
49+
// 尝试加载指定的env文件
50+
if Path::new(&env_file).exists() {
51+
dotenvy::dotenv_override().ok();
52+
dotenvy::from_filename_override(&env_file)?;
53+
Ok(Some(env_file))
54+
} else if env_file != ".file_classification_env" && Path::new(".file_classification_env").exists() {
55+
// 如果指定了自定义env文件但不存在,回退到.file_classification_env
56+
dotenvy::dotenv_override().ok();
57+
dotenvy::from_filename_override(".file_classification_env")?;
58+
Ok(Some(".file_classification_env".to_string()))
59+
} else {
60+
// 如果文件都不存在,创建默认的.file_classification_env
61+
create_default_env_file()?;
62+
dotenvy::dotenv_override().ok();
63+
dotenvy::from_filename_override(".file_classification_env")?;
64+
Ok(None)
65+
}
66+
}
67+
68+
/// 创建默认的环境变量配置文件
69+
fn create_default_env_file() -> Result<(), Box<dyn std::error::Error>> {
70+
let default_content = r#"# File Classification 系统配置文件
71+
# 数据库配置
72+
DATABASE_URL=file_classification.db
73+
DATABASE_TYPE=sqlite
74+
75+
# Web API 配置
76+
BIND_ADDRESS=127.0.0.1
77+
BIND_PORT=8082
78+
79+
# 日志配置
80+
RUST_LOG=info
81+
RUST_LOG_FILE=debug
82+
83+
# CORS 配置
84+
CORS_ENABLED=true
85+
CORS_ORIGIN=http://localhost:8082
86+
"#;
87+
88+
std::fs::write(".file_classification_env", default_content)?;
89+
Ok(())
90+
}
91+
3892
#[actix_web::main]
3993
async fn main() -> std::io::Result<()> {
4094
// 初始化日志系统
@@ -48,8 +102,10 @@ async fn main() -> std::io::Result<()> {
48102

49103
log::info!("正在启动文件分类 Web API...");
50104

51-
// 加载 .env 文件中的环境变量
52-
dotenvy::dotenv().ok();
105+
// 加载环境变量文件
106+
if let Err(e) = load_env_file() {
107+
log::error!("加载环境变量文件失败: {}", e);
108+
}
53109

54110
// 从环境变量中获取数据库连接URL和数据库类型
55111
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");

test.env

46 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)