MEDIA

メディア

  1. TOP
  2. メディア
  3. プログラミング
  4. Spring BootのController徹底解説|springboot controller入門

Spring BootのController徹底解説|springboot controller入門

Spring BootでWebアプリを作り始めると、必ず登場するのがController(コントローラー)です。

しかし、

  • どこまで処理を書くべき?
  • @Controller と @RestController の違いは?
  • springboot controller の設計ってこれでいいの?

と悩む人は多いです。

本記事では、springboot controller の役割・設計・実務での正解を分かりやすく解説します。


■controller の役割は「受付兼ディレクター」

Spring BootのControllerは、簡単に言うと次のような役割を持ちます。

  • 外部からデータを受け取る
  • 適切な処理をServiceに委譲する
  • レスポンスとして結果を返す

つまり、springboot controller は会社で言うフロントディレクターです。

ここで重要なのは、

controller はビジネスロジックを書く場所ではない

と理解することです。


■ @Controller と @RestController の違い

アノテーション 返すもの 用途
@Controller HTML / View MVC構成(テンプレートエンジンで画面を返す)
@RestController JSON API、SPA、モバイルアプリ向けのエンドポイント

現代のWeb開発では、ほとんどが @RestController です。

理由は、

  • SPA(React、Vue、Next.jsなど)との連携
  • モバイルアプリ(Flutterなど)との通信
  • 外部サービスとのAPI連携

といった事情があり、JSONを返すのが前提になっているからです。


■controller にロジックを書くと破滅する理由

初学者がやりがちなControllerの例を見てみます。

@PostMapping("/user")
public User createUser(User user) {
    // validation
    // DB insert
    // transformation
    return user;
}

一見シンプルで良さそうですが、実務ではこれは修正地獄の原因になります。

理由は、

  • Validationが散らばる
  • DBアクセスがControllerに直書きされる
  • 変換処理が増えるとメソッドが肥大化する

正しい考え方は、

Controllerは薄く、ビジネスロジックはServiceに任せる

です。例として、springboot controller を次のように書き換えます。

@PostMapping("/users")
public User createUser(@RequestBody CreateUserRequest request) {
    return userService.createUser(request);
}

このように、Controllerの責務は

  • リクエストを受け取る
  • Serviceに渡す
  • レスポンスを返す

に限定するのが、springboot controller の基本設計です。


■controller とRESTのURL設計

次のようなURL設計を見たことはないでしょうか。

/saveUser
/getAllUser
/updateUser
/deleteUserById

このようなURLでもアプリは動きますが、REST設計としてはNGです。

RESTを意識した良いURL設計は次のようになります。

POST   /users
GET    /users
GET    /users/{id}
PUT    /users/{id}
DELETE /users/{id}

RESTの基本ルールは、

URLに動詞を入れず、リソース(名詞)で表現する

ことです。

こうすることで、

  • 誰が見ても処理内容が予測しやすい
  • HTTPメソッド(GET/POST/PUT/DELETE)と意味が直感的に対応する
  • springboot controller の構造が自然に整理される

■controller とDTOの関係

ControllerでEntityを直接受け取ると、さまざまな問題が発生します。

  • 画面要件やAPI仕様の変更でEntityが頻繁に書き換わる
  • UI側の事情がドメイン層に侵食する
  • 更新してはいけない項目まで上書きされるリスク

そのため、実務ではDTO(Data Transfer Object)を定義して、springboot controller ではDTOだけを扱うのが一般的です。

public class CreateUserRequest {
    private String name;
    private String email;

    // getter / setter など
}

ControllerではこのDTOを受け取り、

  • Validation
  • Serviceへの引き渡し

までを担当し、Entityへの変換はService層で行うのが、springboot controller のベストプラクティスです。


■controller のあるあるアンチパターン

✕ Controllerが太りすぎる

「全部のロジックが詰まっているController」は、メソッド数もコード量も増え、修正のたびに全体を読み直す必要が出てきます。

✕ URLが動詞だらけ

「/createUser」「/getUser」など、動詞が並んだURLはREST的には非推奨です。長期運用を考えると、springboot controller の読みやすさ・拡張性に悪影響を与えます。

✕ エラーハンドリングがない

例外が発生するたびに500エラーを返していると、ログも追いづらく、現場の開発・運用チームが疲弊します。

✕ 戻り値が Map<String, Object> だらけ

「何でも入るから便利」と思いがちですが、型安全性が失われ、IDEの支援も弱まり、保守性が大きく落ちます。


■controller が上手い人の特徴

springbootのcontroller の設計が上手い人には、次のような特徴があります。

  • Controllerは極限まで薄く保たれている
  • URL設計がRESTのルールに沿っている
  • DTOを適切に使い分けている
  • エラーハンドリングが自然に統一されている
  • Swagger/OpenAPIでAPI仕様が可視化されている
  • 認証・認可ロジックがControllerに漏れ出していない

一言でまとめると、

springboot controller =「仕事を振る天才」

という設計ができている状態です。


■controller を綺麗に保つテクニック

● ValidationをServiceに押し込まない

リクエストの形式的なチェック(必須項目、形式エラーなど)は、Controller層(またはBean Validation)で早めに弾きます。これにより、Serviceは「正しい値が来る前提」で実装でき、責務が分離されます。

● 単一責任原則(SRP)を意識する

1メソッド=1機能を意識し、あまりに多くのことをしないようにします。処理が増えてきたら、springboot controller の役割を見直すサインです。

● メソッドの引数が多くなりすぎたらDTO化を検討

引数が3つ以上になってきたら、「リクエストDTOにまとめられないか?」を検討します。コードの見通しとAPIの明確さが向上します。

● 返すデータは明示的な型で

「とりあえずMapで返す」癖は卒業し、専用のレスポンスDTOを定義することで、springboot controller の可読性・保守性を高めましょう。


■controller は「技術の入り口」であり「設計の顔」

Controllerを書いていると、次のような問いに何度も向き合うことになります。

  • どこにロジックを書くべきか
  • 何をどこまで公開するか
  • 誰が変換処理(DTO⇔Entity)を担うか

つまり、springboot controller は、

ソフトウェア設計そのものの理解が問われる層

とも言えます。Controllerのコードを見れば、そのプロジェクトの設計思想がほぼ丸見えです。


■ 参考リンク:Spring Boot公式ドキュメント

Spring Bootのより詳しい仕様や最新情報は、公式ドキュメントが最も信頼できます。

https://spring.io/projects/spring-boot


■ よくある質問(springboot controller)

Q1. Spring BootのControllerはどこまで責任を持つべき?

A. リクエストの受取、バリデーション、Service呼び出し、レスポンス生成までです。ビジネスロジックは基本的にService層に委譲し、springboot controller は「受付兼ディレクター」として振る舞うのが理想です。

Q2. @Controller と @RestController の使い分けは?

A. HTMLなどの画面(テンプレート)を返したい場合は @Controller、JSONを返すAPIを作りたい場合は @RestController を使います。Web API開発では、ほとんどのspringboot controller が後者になります。

Q3. Controllerに共通処理を書くのはあり?

A. ログ出力や認証などの共通処理は、Filter、Interceptor、ControllerAdviceなどに切り出した方が保守性が高いです。springboot controller には「ルートごとの役割」に集中させるのがおすすめです。

Q4. Controllerが肥大化した場合どうする?

A. DTO導入、Serviceの分割、エラーハンドリングの共通化(ExceptionHandler)を行うことでスリム化できます。また、URL設計と責務分担を見直すことで、springboot controller の見通しが一気に良くなります。


■ まとめ:springboot controller を制する者は、プロジェクトを制す

Spring Bootは便利で、Controllerも簡単に書けます。しかし、簡単に書けてしまうからこそ、設計の差がはっきりと出ます。

controller をうまく設計するためのポイントは次の通りです。

  • RESTを意識したURL設計を行う
  • Controllerは薄く保ち、Serviceにロジックを寄せる
  • DTOとEntityを分けて扱う
  • 責務分担とエラーハンドリングを意識する

これだけで、現場では「できる人」扱いされるレベルのspringboot controller が書けるようになります。


■ 最後に:springbootのcontroller が楽しくなる瞬間が来る

最初のうちは、springbootのcontroller の設計に悩むことも多いはずです。しかし、設計やアーキテクチャの考え方が身についてくると、次第にControllerを書くのが楽しくなります。

その先には、

  • 美しい設計
  • 高い保守性
  • チームメンバーの幸福
  • 自分自身の市場価値の向上

が待っています。

そして、もし 「もっと体系的に学びたい」「実務レベルの設計力を身につけたい」 と感じた方は、次のステップとして zerocode を活用することをおすすめします。

開発現場で必要とされる技術や設計思考を、短期間で効率よく学べるオンライン学習サービスです。

Spring Boot、API設計、アーキテクチャなど、実務でそのまま使える知識が身につきます。

学習の次のステージへ進みたい方はこちら:ZeroCode

Join us! 未経験からエンジニアに挑戦できる環境で自分の可能性を信じてみよう 採用ページを見る→

記事監修

ドライブライン編集部

[ この記事をシェアする ]

記事一覧へ戻る