30.

独自のエラーページを定義する方法 (Servlet / Spring Boot / Laravel / Apache)

編集
この記事の要点
  • Servlet / JSP: web.xml で 404 / 500 を指定
  • Spring Boot: src/main/resources/templates/error/404.html を置くだけ
  • 例外単位: @ControllerAdvice + @ExceptionHandler
  • Laravel: resources/views/errors/404.blade.php
  • Apache: ErrorDocument 404 /404.html

1. Servlet / JSP (web.xml)

従来の Java Web アプリは WEB-INF/web.xml でステータスコードや例外単位にエラーページを指定:




    
    
        404
        /WEB-INF/jsp/error/404.jsp
    

    
        500
        /WEB-INF/jsp/error/500.jsp
    

    
    
        java.lang.Throwable
        /WEB-INF/jsp/error/500.jsp
    

    
        com.example.BusinessException
        /WEB-INF/jsp/error/business.jsp
    

<%-- 404.jsp --%>
<%@ page isErrorPage="true" pageEncoding="UTF-8" %>


404 Not Found

ページが見つかりません

URL: <%= request.getAttribute("javax.servlet.error.request_uri") %>

ステータス: <%= request.getAttribute("javax.servlet.error.status_code") %>

トップへ

2. Spring Boot のエラーページ

Spring Boot は規約に従ってファイルを置くだけで自動的にカスタムエラーページが有効化:

src/main/resources/
├── templates/
│   └── error/
│       ├── 404.html        ← 404 専用
│       ├── 500.html        ← 500 専用
│       ├── 4xx.html        ← 4xx 全般
│       └── 5xx.html        ← 5xx 全般
└── static/
    └── error/
        └── 404.html        ← 静的エラーページ (Thymeleaf 不使用時)



404 Not Found

ページが見つかりません

URL: /foo

ステータス: 404

メッセージ: Not Found

トップへ

application.properties でカスタマイズ:

# エラー情報の出力制御
server.error.include-stacktrace=never       # 本番はスタックトレース非表示
server.error.include-message=always
server.error.include-binding-errors=always
server.error.include-exception=false
server.error.whitelabel.enabled=false       # 既定の Whitelabel を無効化

# エラーパス変更
server.error.path=/error

3. Spring Boot の @ControllerAdvice

例外単位で柔軟に処理を分けたい場合は @ControllerAdvice:

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 業務例外 → 専用画面へ
    @ExceptionHandler(BusinessException.class)
    public String handleBusiness(BusinessException ex, Model model) {
        model.addAttribute("message", ex.getMessage());
        return "error/business";
    }

    // 404 系 → カスタム 404 ページ
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handle404(NoHandlerFoundException ex) {
        return "error/404";
    }

    // 想定外 → 500 ページ
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleAll(Exception ex, Model model) {
        log.error("予期せぬエラー", ex);
        model.addAttribute("traceId", MDC.get("traceId"));
        return "error/500";
    }
}

// REST API の場合は @RestControllerAdvice + ResponseEntity
@RestControllerAdvice
public class ApiExceptionHandler {
    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity> notFound(EntityNotFoundException ex) {
        return ResponseEntity.status(404)
            .body(Map.of("error", "not_found", "message", ex.getMessage()));
    }
}

404 を Spring Boot で捕まえるには下記設定も必要:

spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

4. Laravel のエラービュー

Laravel は resources/views/errors/ 配下に対応するステータスコードのファイルを置くだけ:

resources/views/errors/
├── 404.blade.php
├── 419.blade.php   ← CSRF expired
├── 500.blade.php
└── 503.blade.php   ← メンテナンス
{{-- resources/views/errors/404.blade.php --}}
@extends('layouts.app')

@section('title', '404 Not Found')

@section('content')

404

お探しのページが見つかりません

トップへ
@endsection {{-- $exception で例外オブジェクトにアクセス可 --}} {{-- {{ $exception->getMessage() }} --}}

柔軟に処理を変えたい場合は app/Exceptions/Handler.php:

public function register(): void
{
    $this->renderable(function (NotFoundHttpException $e, $request) {
        if ($request->is('api/*')) {
            return response()->json(['error' => 'not_found'], 404);
        }
        return response()->view('errors.404', [], 404);
    });
}

5. Apache / nginx のエラーページ

# .htaccess または httpd.conf
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ErrorDocument 503 /errors/maintenance.html

# 外部 URL にリダイレクト
ErrorDocument 404 https://example.com/notfound
server {
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    location = /404.html {
        internal;
        root /usr/share/nginx/html;
    }

    # API のみ JSON で返す
    location /api {
        error_page 404 = @json_404;
    }
    location @json_404 {
        default_type application/json;
        return 404 '{"error":"not_found"}';
    }
}

表示確認のコツ

確認方法コマンド / 操作
404 を出す適当な URL /notexist をブラウザで叩く
500 を出すテスト用 endpoint /test/errorthrow new RuntimeException()
Status を確認curl: curl -I http://localhost/notexist
JSON / HTML の出し分けcurl: -H "Accept: application/json" で差分確認

FAQ

Q: Spring Boot で 404 が error/404.html に行かない
A: spring.web.resources.add-mappings=false を設定して静的リソースの自動マッピングを無効化。さらに throw-exception-if-no-handler-found=true を有効化。

Q: 本番でスタックトレースが表示されてしまう
A: Spring Boot は server.error.include-stacktrace=never。Laravel は .envAPP_DEBUG=false

Q: メンテナンス画面を出したい
A: nginx で 503 と Retry-After ヘッダ。Laravel なら php artisan down --render="errors::503"

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール(eclipseプラグイン)
  2. クイックスタート
  3. プロジェクトの作成
  4. Spring Bootプロジェクトの作成
  5. Spring Bootプロジェクトの実行
  6. Spring BootでHello World!
  7. アノテーション一覧
  8. DB接続設定からエンティティおよびリポジトリの作成、値の取得まで(JPA編)
  9. DB接続設定や値の取得(JdbcTemplate編)
  10. ビューから値をモデルに格納しコントローラーで受け取る方法
  11. コントローラーにてモデルに値を格納してビューに渡す方法
  12. テンプレートエンジン
  13. ModelとModelAndViewの違い
  14. AOPの使用方法
  15. classpath: 内部ファイルの読み込み
  16. file: 外部ファイルの読み込み
  17. CSVファイルアップロード方法(Ajax)
  18. CSVファイルダウンロード方法(Ajax)
  19. Spring Bootプロジェクトのビルドと本番環境へのデプロイ方法(内部tomcat使用)
  20. Application.propertiesの環境依存設定の分割方法
  21. JPAにおけるEntityManagerの取得方法
  22. JPAにおけるjava.sql.Connectionの取得方法
  23. エラー一覧
  24. jarの引数を受け取る方法
  25. Spring BootでGmailからメール送信
  26. 複数のDBに接続する設定(Spring Boot & JPA編)
  27. ポート番号の変更
  28. Basic認証の実装と特定のURLに限定する方法
  29. Spring SecurityのBasic認証の無効化
  30. 独自のエラーページを定義する方法
  31. プロパティファイルの値やjar実行時の引数を取得する方法