目的
SpringBootアプリケーションからaxumへ移行したくなった時に、設定ファイル(resourcesフォルダのapplication.yaml群)を手軽に移送する方法をまとめるものです。
前提
環境 | 値 |
---|---|
OS | Mac(M1) |
Language | Rust 1.89.0 |
Rust Edition | 2024 |
FrameWork | axum 0.8 |
IDE | Zed 0.203.4 |
手順
- SpringBootのresourcesフォルダをaxumルートフォルダにコピペ
-
clap
・config
・serde
クレートを追加 -
profile
引数を定義 -
profile
に応じた設定ファイルの読み込み処理実装 - 読み込んだ定義情報を
State
設定 - 動作確認
1. SpringBootのresourcesフォルダをaxumルートフォルダにコピペ
SpringBootのresourcesフォルダをそのままaxumルートフォルダにコピペします。
SpringBootプロジェクト
└src
└main
└resources
↓ コピペ
axumプロジェクト
└resources
2. clap
・config
・serde
クレートを追加
cargoを使ってクレートを追加します。
cargo add config
cargo add clap --features derive
cargo add serde --features derive
3. profile
引数を定義
clap
クレートを使って引数を定義します。
SpringBootと同じ感覚で使えるよう、引数名はprofile
にします。
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about)]
struct Args {
#[arg(short = 'p', long, default_value = "dev")]
profile: String,
}
4. profile
に応じた設定ファイルの読み込み処理実装
config
とserde
クレートを使って設定ファイルを読み込みます。
インフォメーション
設定ファイルはお試し用にhoge
とfuga
を記述しています。
お試しapplication.yamlはこちら
# application.yaml
hoge: hoge
# application-dev.yaml
fuga: devfuga
# application-stg.yaml
test: stghoge
fuga: stgfuga
# application-prd.yaml
hoge: prdhoge
#[derive(Debug, Deserialize, Clone)]
pub struct AppConfig {
pub hoge: String,
pub fuga: Option<String>,
}
impl AppConfig {
pub fn load(profile: String) -> Result<Self, Box<dyn StdError>> {
let config = Config::builder()
.add_source(config::File::with_name("resources/application"))
.add_source(
config::File::with_name(&format!("resources/application-{}", profile)).required(true),
)
.build()
.unwrap();
Ok(config.try_deserialize::<AppConfig>()?)
}
}
5. 読み込んだ定義情報をState
設定
#[tokio::main]
async fn main() {
let app_config = AppConfig::load(Args::parse().profile).unwrap();
let app = Router::new()
.route("/", get(root_handler))
.with_state(app_config) // ここでStateとして設定
.layer(TraceLayer::new_for_http());
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
tracing::debug!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
// Stateを引数として取得し、参照する
async fn root_handler(State(app_config): State<AppConfig>) -> String {
format!(
"Hello, axum {} {}!!!",
app_config.hoge,
app_config.fuga.unwrap_or_default()
)
}
6. 動作確認
引数で指定するprofile
に応じてアクセス時に表示される結果が変わることが確認できれば成功です。
cargo run #省略した場合はdev適用
cargo run -- --profile=stg #引数名は短縮しなくてもいいし、
cargo run -- -p=prd #短縮形で指定してもOK
おまけ
最初はfigment
使っていたんですが、config
クレートの方がシンプルかつ便利でした。
Rocket使ったことないですが、そっちの場合はfigment
の方がいいみたいですね。