1. test 1
  2. test 2
  3. test 3
  4. test 4
  5. test 5
  6. test 6
  7. test 7
コース一覧
Spring Boot入門
設定値の外部化

Spring Boot入門

Java で Web API サーバーを作るための Spring Boot の入門コースです。DI コンテナ、REST コントローラ、リクエスト検証、レイヤ分割、Spring Data JPA、例外ハンドリング、テストまでを扱います。毎レッスン、Spring が裏側でやっている判断そのものを pure Java の関数として自分で書き、フレームワークが何を肩代わりしてくれているのかを手触りで理解できる構成にしました。約 12 時間 (1 日 30 分 × 24 日) で 48 レッスンを修了できます。

1
Spring Bootとは何か
01. Spring Bootで何が作れるのか10分
02. サーブレットからフレームワークへ15分
03. ルーティング表という発想15分
04. プロジェクトの構成10分
05. 起動のしくみと自動設定15分
06. パスのマッチング15分
2
DIコンテナ
01. newで書くと何が困るのか15分
02. コンストラクタインジェクション15分
03. インターフェースへの依存15分
04. @Componentと@Bean15分
05. 自作のDIコンテナ20分
06. Beanのスコープとライフサイクル15分
3
RESTコントローラ
01. RESTという設計方針15分
02. @RestControllerの役割15分
03. @GetMappingとパス変数15分
04. クエリパラメータの受け取り15分
05. @PostMappingとリクエストボディ15分
06. ステータスコードの選び方15分
07. ResponseEntityで組み立てる15分
4
リクエストとレスポンスの変換
01. JSONとオブジェクトの往復15分
02. DTOとエンティティを分ける15分
03. recordでDTOを書く15分
04. 入力検証の基本15分
05. 検証エラーをまとめて返す15分
06. アノテーションによる検証15分
5
レイヤ構成とビジネスロジック
01. 3層アーキテクチャ10分
02. @Serviceに置くもの15分
03. 状態遷移をルールにする15分
04. 料金計算のような業務ロジック15分
05. @Transactionalとは何か15分
06. トランザクションの巻き戻し15分
6
データアクセス
01. @Entityとテーブルの対応15分
02. リポジトリという抽象15分
03. メソッド名からクエリを作る20分
04. 検索条件の組み立て15分
05. ページングと並び替え15分
06. N+1問題15分
7
例外処理と横断的関心事
01. 例外をHTTPに変換する15分
02. @ExceptionHandlerと@ControllerAdvice15分
03. エラーレスポンスの形を決める15分
04. フィルタとインターセプタ15分
05. ログとリクエストの追跡15分
06. 設定値の外部化15分
8
テストと仕上げ
01. テストの種類と使い分け15分
02. Serviceの単体テスト15分
03. モックで依存を差し替える15分
04. MockMvcでエンドポイントを試す15分
05. 本番へ出すための次の一歩10分

設定値の外部化

このレッスンでは、接続先やポート番号といった環境ごとに変わる値を、コードから追い出す方法を身につけます。

ハードコードすると環境を移せません

データベースの接続先を Java のコードに直接書いてしまうと、開発機と本番で別々のソースを持つことになります。パスワードを書けば、そのままリポジトリに残って外へ出ます。環境によって変わる値は、コードではなく設定として外に置く。これが基本です。

Spring Boot は src/main/resources の下に置いた application.properties または application.yml を起動時に自動で読み込みます。同じ内容を 2 つの書き方で表すと次のようになります。

Properties

server.port=8080 app.name=shop app.mail.from=noreply@example.com app.mail.retry-count=3

YAML

server: port: 8080 app: name: shop mail: from: noreply@example.com retry-count: 3

properties はキーが全部書かれていて検索しやすく、yml は階層が視覚的で長いキーの重複が減ります。どちらを選んでも読み込まれる中身は同じです。1 つのプロジェクトではどちらかにそろえてください。

取り出し方は @Value と @ConfigurationProperties

1 つの値をぱっと取り出したいときは @Value が手軽です。

Java

@Component public class MailSender { @Value("${app.mail.from}") private String from; @Value("${app.mail.retry-count:3}") private int retryCount; // 設定が無ければ 3 になる }

角括弧ではなく波括弧とドル記号で囲む記法で、中に既定値も書けます。ただし値が増えてくると @Value は散らかります。関連する値をまとめて 1 つの型に束ねるのが @ConfigurationProperties です。

Java

@ConfigurationProperties(prefix = "app.mail") public record MailProperties(String from, int retryCount) {}

この 1 行で app.mail.from と app.mail.retry-count が対応するフィールドへ入ります。ハイフンつなぎのキーがキャメルケースのフィールドへ結び付く点も便利です。型が付くので誤りに早く気づけますし、この型を注入すれば設定がどこで使われているかも追えます。設定が 3 つ以上あるなら、迷わずこちらを選んでください。

プロファイルで環境ごとに切り替えます

環境ごとの差分は、プロファイルという仕組みで分けます。application-dev.properties と application-prod.properties を用意し、起動時に有効なプロファイル名を指定すると、共通の application.properties に加えてその環境用のファイルが重ねて読み込まれます。同じキーがあれば、プロファイル側が勝ちます。

最後に勝つのは環境変数です

設定値の出どころは 1 つではありません。優先順位は大まかに、コマンドライン引数、環境変数、プロファイル別のファイル、共通のファイル、コード内の既定値の順で、上にあるものが下を上書きします。この順序があるおかげで、コンテナで動かすときにファイルを書き換えることなく、環境変数だけで接続先を差し替えられます。

キーの対応にも決まりがあります。app.mail.from に対する環境変数は APP_MAIL_FROM です。ドットをアンダースコアにして大文字にする、と覚えてください。パスワードや API キーは、ファイルではなくこの経路で渡すのが定石です。

演習で書くもの

Spring がやっている「設定ファイルを読んでキーで引き、無ければ既定値を使う」という処理を、自分で書きます。コメント行と空行を飛ばす部分が、実際のファイルを読むときに必ず要る処理です。

要件

  1. 空行と井桁で始まるコメント行を読み飛ばすこと
  2. 最初のイコールで区切り、キーと値の前後の空白を取り除くこと
  3. 同じキーはあとに書かれた方を採用し、見つからなければ既定値を返すこと

入出力例

lookupProperty("# app settings server.port=8080 app.name=shop # mail app.mail.from=noreply@example.com ", "server.port", "8000") → "8080" lookupProperty("# app settings server.port=8080 app.name=shop # mail app.mail.from=noreply@example.com ", "app.mail.from", "none") → "noreply@example.com" lookupProperty("# app settings server.port=8080 app.name=shop ", "app.timeout", "30") → "30" lookupProperty("#server.port=9999 ", "server.port", "8080") → "8080" lookupProperty("app.name = shop ", "app.name", "x") → "shop" lookupProperty("app.name=first app.name=second ", "app.name", "x") → "second" lookupProperty("", "app.name", "fallback") → "fallback"

ヒント

行に分けるには content.split("\n", -1) を使います。各行はまず trim します

区切りの位置は indexOf('=') で求めます。lastIndexOf ではないので、値の中にイコールがあっても壊れません

Map に put していけば、同じキーは自然にあとの値で上書きされます

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/08/09

関連レッスン

  • テストの種類と使い分け

    @SpringBootTest と @WebMvcTest の違いを確認します。

  • ログとリクエストの追跡

    リクエストを識別する ID を組み立て、追跡できるようにします。

  • フィルタとインターセプタ

    連なった処理を順に通すチェーンを実装します。

  • エラーレスポンスの形を決める

    一貫したエラー本文を組み立てられるようになります。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • ポート番号1台のサーバーで複数のサービスを区別するための番号。
  • データベースデータを構造化して保存する仕組み
  • パスワードDBが漏洩しても元のパスワードがわからないようにするため。
  • リポジトリプロジェクトの保管場所
  • 階層ネットワークを役割ごとに積み重ねた構造
  • 関連クラス間のつながりを表す直線
  • フィールドクラスが持つデータ
  • キャメルケースmyProject 形式。JS 変数向け
main.java
学習モード
エディタを読み込んでいます

メモ

設定値の外部化

⌘S で保存