初心者がやりがち!Spring Bootの落とし穴7選とその回避法
こんにちは。ゆうせいです。
Spring Bootは、JavaによるWebアプリケーション開発のハードルをぐっと下げてくれる素晴らしいフレームワークです。しかし、「簡単に書ける」からこそ、初心者が知らず知らずのうちにやってはいけない実装に手を出してしまうことも少なくありません。
今回は、Spring Boot初学者がよくやってしまうミス7選を、具体的なコード例や図解とともに解説します!
1. セッションに何でも入れてしまう
問題点:
セッションはログイン状態や一時的なフラグなど、「最低限の情報」を保持するための仕組みです。検索結果の一覧やフォームの状態などを何でも詰め込むと、メモリ不足や意図しない動作の原因になります。
例:
session.setAttribute("form", form);
session.setAttribute("searchResultList", hugeList);
解決策:
- フォームの一時データは
@ModelAttribute
に - リダイレクト間のデータは
RedirectAttributes
を使う - セッションは最終手段と心得よう!
2. ViewからViewへ直接遷移する
問題点:
テンプレートファイルに直接リンクすると、コントローラーを経由しないため、初期化処理やセキュリティチェックが抜け落ちるリスクがあります。
NG例:
<a href="/templates/form.html">フォームへ</a>
解決策:
@GetMapping("/form")
public String showForm(Model model) {
model.addAttribute("form", new Form());
return "form";
}
<a th:href="@{/form}">フォームへ</a>
3. コントローラーにビジネスロジックを全部書いてしまう
問題点:
コントローラーに全て詰め込むと、責任が曖昧になりテストが困難になります。バリデーション、DB操作、状態管理などが混在していると、再利用性も失われます。
解決策:
- ビジネスロジックは
@Service
クラスに分離 - コントローラーは「データの受け取りと渡すだけ」に徹する
4. 設定ファイルを環境ごとに分けていない
問題点:
application.properties
を1つしか使っていないと、開発用設定がそのまま本番で使われることがあります。これは、セキュリティ事故やパフォーマンス問題の原因になりかねません。
解決策:
- Springのプロファイル機能を活用しよう!
# application-dev.properties
spring.datasource.url=jdbc:h2:mem:test
# application-prod.properties
spring.datasource.url=jdbc:mysql://本番DB
起動時に --spring.profiles.active=prod
を指定すれば切り替えできます。
5. バリデーションをフロント側だけに任せる
問題点:
JavaScriptだけで入力チェックをしていると、悪意のあるリクエストに無防備になります。サーバー側でのバリデーションがなければ、危険な値がそのまま登録されてしまう可能性も。
解決策:
@Valid
アノテーションとBindingResult
を併用- Bean Validation(JSR-380)を使えば簡潔に記述できます!
@PostMapping("/submit")
public String submit(@Valid @ModelAttribute Form form, BindingResult result) {
if (result.hasErrors()) return "form";
service.save(form);
return "redirect:/done";
}
6. 共通の例外処理をしない
問題点:
例外が発生したとき、白い画面に英語のエラーだけが出てくると、ユーザーは困惑し、開発者もデバッグに時間がかかります。
解決策:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e, Model model) {
model.addAttribute("message", "予期せぬエラーが発生しました。");
return "error";
}
}
@ControllerAdvice
で例外ハンドリングを共通化
7. 入力値を直接エンティティにバインドする
問題点:
フォームから受け取ったデータをそのままDBエンティティに渡すと、意図しないデータ上書きやセキュリティ上の問題が起こる可能性があります。
解決策:
- 入力用の DTO(Data Transfer Object) を作成し、Entityとは分離
- DTO → Entity 変換は Service層で明示的に行う
例:
public class UserForm {
private String name;
private String email;
}
public User toEntity(UserForm form) {
return new User(form.getName(), form.getEmail());
}
一覧表:7つの典型的なミスと対策
番号 | ミス内容 | 問題点 | 推奨される対応策 |
---|---|---|---|
1 | セッションに何でも保存 | メモリ圧迫、状態の混乱 | Flash属性やModelで管理 |
2 | ViewからViewに直接遷移 | コントローラー処理がスキップされる | Controllerを必ず経由 |
3 | ロジックをControllerに直書き | 責任不明瞭、テスト困難 | Service層に処理を分離 |
4 | 環境別の設定を分けていない | 本番環境で事故が起きる | Profileで環境を分離 |
5 | バリデーションをフロントだけに依存 | サーバー側が無防備 | @ValidとBindingResultを活用 |
6 | 共通の例外処理をしていない | ユーザーに不親切、デバッグ困難 | @ControllerAdviceを使う |
7 | 入力値をEntityに直接バインドしている | セキュリティ・データ整合性の問題 | DTOを作り、Entityと分離 |
今後の学習の指針
これらのポイントを意識するだけで、アプリケーションの品質や保守性が一段階アップします!
次に学ぶと良いトピックは以下の通りです。
- Springのスコープ(@RequestScope, @SessionScope)の違い
- Model, RedirectAttributes, DTOの設計パターン
- Spring Securityによる画面制御とアクセス制御
- 例外ハンドリングとログ出力の設計
迷ったら「なぜこの方法が推奨されるのか?」と一度立ち止まって考えるのが、実力アップの近道です。じっくりと、でも確実に学んでいきましょう!
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール

- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。