この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: 独自のエラーページを定義する方法
SEOタイトル: 独自のエラーページを定義する方法 (Servlet / Spring Boot / Laravel / Apache)

この記事の要点
  • Servlet / JSP: web.xml<error-page> で 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 でステータスコードや例外単位にエラーページを指定:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" version="6.0">

    <!-- ステータスコード別 -->
    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/error/404.jsp</location>
    </error-page>

    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/jsp/error/500.jsp</location>
    </error-page>

    <!-- 例外クラス別 -->
    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/WEB-INF/jsp/error/500.jsp</location>
    </error-page>

    <error-page>
        <exception-type>com.example.BusinessException</exception-type>
        <location>/WEB-INF/jsp/error/business.jsp</location>
    </error-page>

</web-app>
<%-- 404.jsp --%>
<%@ page isErrorPage="true" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head><title>404 Not Found</title></head>
<body>
<h1>ページが見つかりません</h1>
<p>URL: <%= request.getAttribute("javax.servlet.error.request_uri") %></p>
<p>ステータス: <%= request.getAttribute("javax.servlet.error.status_code") %></p>
<a href="${pageContext.request.contextPath}/">トップへ</a>
</body>
</html>

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 不使用時)
<!-- templates/error/404.html (Thymeleaf) -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>404 Not Found</title></head>
<body>
<h1>ページが見つかりません</h1>
<p>URL: <span th:text="${path}">/foo</span></p>
<p>ステータス: <span th:text="${status}">404</span></p>
<p>メッセージ: <span th:text="${error}">Not Found</span></p>
<a th:href="@{/}">トップへ</a>
</body>
</html>

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<Map<String, String>> 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')
<div class="text-center py-20">
    <h1 class="text-6xl">404</h1>
    <p>お探しのページが見つかりません</p>
    <a href="{{ url('/') }}" class="btn btn-primary">トップへ</a>
</div>
@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 '{&quot;error&quot;:&quot;not_found&quot;}';
    }
}

表示確認のコツ

確認方法コマンド / 操作
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"