学習・技術検証用デモ — 本システムは実際の銀行サービスではありません。

公開情報をもとに構築した教育目的のシステムです。実在する個人情報・口座情報・機密情報・認証情報等を入力しないでください。

ミニ銀行ACADEMY SYSTEM LEARNING
教材メニュー
学習進捗0 / 134
あと134項目
INTERMEDIATE · 中級COURSE 05 · JAVA / ENTERPRISE DEVELOPMENT

Controller:HTTP境界を薄く保つ

Controllerは画面から届くHTTPをJavaの型へ変換し、ユースケースを呼び、決められたHTTPレスポンスへ戻す境界です。金融ルールを置かない理由まで学びます。

03 / 11
JAVA / ENTERPRISE DEVELOPMENT · Java・エンタープライズ開発

Java / Spring Bootを入口に、金融システムのService・Repository・Transaction設計を読む。

先に学ぶ内容 — Prerequisite: ソフトウェア工学 / 銀行システム

学ぶこと — LEARNING GOALS

このページで学ぶこと

  • @RestControllerとルーティング
  • Bean Validationとヘッダー検証
  • 成功・失敗レスポンスを統一する方法

体験35 · JAVA CONTROLLER(境界を薄く保つ)

振込先の名義を、利用者が入力したそのままの値で使ってよいか確かめよう

まずは予想をひと言。本文を読んだ後、教材内の参照元で実際のDTOと例外処理を確認します。

体験学習 · STEP 1 / 5
  1. 01
    まず予想する — PREDICT

    まずここだけ:思ったことをひと言書く

    振込先の銀行名や名義を、利用者が入力したrequest bodyの値そのまま使ってよいと思いますか?

    正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。

    ヒント1を見る

    利用者が入力した値を、そのまま信じてよいでしょうか?

    ヒント2を見る

    振込先の正式な名義は、どこで確定させるべきでしょうか?

    もっと詳しく:この問いで使う専門用語
    • DTOは、HTTPで受け渡す項目を表す専用の型です。
    • Bean Validationは、注釈で入力形式の制約を宣言する仕組みです。
    • Controller Adviceは、複数Controllerの例外処理をまとめる仕組みです。
まずはひと言だけで大丈夫です。

この後の本文を最後まで読んでから、実際に操作して確かめるステップへ進みます。

日常語で理解する — PLAIN LANGUAGE

まず、ここだけつかむ

1

ControllerはHTTPリクエストを受け、形式を検証し、Serviceを呼び、HTTPレスポンスへ整える境界です。

2

金額やOTPの形式は入口で拒否しますが、残高・KYC・所有者のような業務判断はDB側へ委ねます。

3

既知の失敗と想定外の失敗をGlobalExceptionHandlerで安全な共通JSONへ変換し、生の内部情報を外へ出しません。

順番に理解する — DIFFICULT PARTS, STEP BY STEP

難しいポイントを、順番にほどく

専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。

01

DTO

やさしく言うと

HTTPで受け渡す項目を表す専用の型です。

なぜ必要?

外部契約と内部モデルを分け、公開項目を制御するためです。

Minibankでは

CreatePaymentRequestとCreatePaymentResponseを分けています。

02

Bean Validation

やさしく言うと

注釈で入力形式の制約を宣言する仕組みです。

なぜ必要?

不正な形式をユースケースへ渡す前に一貫して拒否するためです。

Minibankでは

@Digits、@Size、@Patternなどを使います。

03

Controller Advice

やさしく言うと

複数Controllerの例外処理をまとめる仕組みです。

なぜ必要?

エラー形式と情報公開方針を一貫させるためです。

Minibankでは

GlobalExceptionHandlerがcode・message・requestIdを返します。

発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。

Payment APIの2つの入口

@RequestMappingが共通パス、@PostMappingが個別操作を定義します。@RequestBodyはJSON、@RequestHeaderはHTTPヘッダー、@PathVariableはURL内の値を受け取ります。

HTTP役割主な結果
POST /api/v1/payments振込依頼を作りOTP待ちにする201 Created
POST /api/v1/payments/{paymentId}/confirmOTPを確認し振込実行へ進める期待される業務結果は200 OK

入力検証は入口で早く失敗させる

@ValidによりDTOの制約が検査されます。OTPは空でなく6桁の数字、金額は1以上の整数、memoは最大200文字という形式契約があります。

形式が正しくても、本人の振込依頼か、期限内か、残高があるかは分かりません。それらはDB側の業務検査です。

public record ConfirmPaymentOtpRequest(
    @NotBlank
    @Pattern(regexp = "^\\d{6}$")
    String otpCode
) {}

認証情報と冪等キーもAPI契約

  • AuthorizationはBearer形式であることをControllerが確認
  • Bearer tokenの本人性と権限は転送先のPostgREST・PostgreSQLが判断
  • Idempotency-KeyはUUIDとして解析し、不正な形式を拒否
  • 振込先の銀行名・支店名・名義はクライアントから受け取らず、DB側で解決

例外変換を一か所へ集める

@RestControllerAdviceのGlobalExceptionHandlerが、ApiException、入力エラー、想定外例外を統一JSONへ変換します。

想定外例外はサーバーログへ記録しますが、クライアントへスタックトレースや生のPostgreSQLメッセージを返しません。requestIdによって利用者の応答と内部ログを結びます。

分類外部応答内部で残すもの
既知の業務・認可エラー安定したcodeと安全なmessagerequestId
入力形式エラーVALIDATION_ERROR検証失敗の診断情報
想定外例外INTERNAL_ERRORの一般文言stack traceとrequestId

体験学習の続き · LEARNING LOOP

ここまで読めましたか?続けて確認してみましょう

DTOとController Adviceの考え方を読んだところで、教材内の参照元で実際のDTOと例外処理を確認し、自分の言葉で説明してみます。

STEP 2〜5 / 5
  1. 02
    仕組みを確かめる — CONCEPT CHECK

    画面操作なしで、仕組みを確かめる

    この仕組みは、Mini Bankの画面には現れません。次のEvidenceとCode Trail、教材本文だけで理解を進めます。

  2. 03
    証拠を確認する — EVIDENCE

    何を見たか、1つずつ確かめる

    Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。

    画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。

  3. 04
    コードの処理経路を追う — CODE TRAIL

    コードを書く必要はありません

    ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。

    まずControllerが何を受け取り何を検査するかを見て、次に例外がどう安全な応答へ変換されるかを見ます。

    HTTP受付とユースケース呼び出し。

    services/payment-service/src/main/java/com/minibank/payment/controller/PaymentController.java

    例外から安全なHTTP応答への変換。

    services/payment-service/src/main/java/com/minibank/payment/error/GlobalExceptionHandler.java
    教材の参照元を確認する — Source Trail ↓
  4. 05
    自分の言葉で説明する — EXPLAIN

    LEVEL 1 — やさしい説明(まずここだけ)

    なぜControllerは振込先名義をrequestから受け取らず、DB側の解決結果を使うのでしょうか? 短い2文を目安に説明してください。

    日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。

    ヒント1を見る

    「DTO」と「Bean Validation」という2つの言葉を使って書いてみましょう。

    ヒント2を見る

    形式が正しいことと、内容が正しいことの違いを考えてみましょう。

    もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)

    DTO、Bean Validation、Controller Adviceの3つを使って、ControllerがHTTP境界をどう薄く保つか説明してみましょう。

    挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。

    説明の確認ポイント — Checkpoint
    • 形式検査と業務判断が別の場所にあると説明できる
    • 内部情報が外部応答へ漏れないと説明できる
予想5文字以上・証拠2項目・説明20文字以上で完了できます。

証拠の確認:0 / 2。LEVEL 2(専門用語での説明)は任意です。

入力はこのブラウザに保存されます。Academy教材の進捗とは別の学習メモです。

理解を確かめる — CHECK YOUR UNDERSTANDING

3問で理解チェック

答えを頭の中で考えてから、各項目を開いて確認してください。

Q1Bearerという文字列を確認すれば認証完了ですか?
答え

いいえ。Controllerは形式を確認し、tokenの有効性と権限はPostgREST・PostgreSQL側が判断します。

Q2なぜ振込先名義をrequest bodyから受け取らないのですか?
答え

利用者による改ざんを避け、口座番号からDB側で正式情報を解決するためです。

Q3想定外例外のstack traceを利用者へ返しますか?
答え

返しません。内部ログへ残し、外部には一般的なINTERNAL_ERRORを返します。

ここまで読めましたか?

完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。

教材の参照元 — SOURCE TRAIL

根拠と関連教材

CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。

確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。

  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/controller/PaymentController.javaHTTP受付とユースケース呼び出し
  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/controller/dto/CreatePaymentRequest.java振込依頼の入力制約
  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/error/GlobalExceptionHandler.java例外から安全なHTTP応答への変換