#author("2021-07-01T02:16:22+00:00","","")
#author("2021-07-01T02:17:52+00:00","","")
[[第3回]]

* 例外処理 [#a8f302bb]
- テキストはパワーポイント参照のこと

** 例外処理を加えたレイヤ構造 [#d9912640]
- &attachref(controller_advise.png);
- &attachref(controller_advice.png);

*** 解説 [#r435b950]
- コントローラ・アドバイス(@ControllerAdvice)は,各レイヤで投げられた例外を
まとめて受け取って処理する''例外処理専用''のクラス
- コントローラ・アドバイスの各メソッドは,例外の種類に応じた処理をメソッドとして定義する
-- 例外マッピング(例外→メソッド)
-- メソッドの前にアノテーション@ExceptionHandler(例外クラス.class)を付与する 
- メソッドの中では,例外時の処理(例:ログを取る)およびエラー画面の生成指示を行う
- 例外処理メソッドをコントローラ・アドバイスを定義せずに,コントローラ書いてもよい
-- その場合は,そのコントローラが呼び出すサービス以下の例外を優先的にキャッチする
-- コントローラでキャッチできなかった例外は,アドバイスで受ける
-- それでもキャッチできない場合は,White Labelの画面が出る


** ToDoアプリの例外処理 [#u10d8988]
*** ControllerAdvice - コントローラ・アドバイス[#bda0508b]
- controller/ToDoErrorHandler.java

 package jp.ac.kobe_u.cs.itspecialist.todoapp.controller;
 
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 
 import jp.ac.kobe_u.cs.itspecialist.todoapp.exception.ToDoAppException;
 import lombok.extern.slf4j.Slf4j;
 
 /**
  * ToDoアプリの例外ハンドラクラス
  */
 @Slf4j
 @ControllerAdvice
 public class ToDoErrorHandler {
     /**
      * アプリケーション例外をハンドルし,エラーページを表示する
      */
     @ExceptionHandler(ToDoAppException.class)
     public String handleToDoException(ToDoAppException ex, Model model) {
         model.addAttribute("advice", "アプリケーション例外が発生しました.メッセージを確認してください");
         model.addAttribute("exception", ex);
         log.error(ex.getMessage());
         return "error";
     }
 
     /**
      * その他の例外をハンドルし,エラーページを表示する
      */
     @ExceptionHandler(Exception.class)
     public String handleException(Exception ex, Model model) {
         model.addAttribute("advice", "深刻なエラーが発生しました.管理者にお問い合わせください");
         model.addAttribute("exception", ex);
         log.error(ex.getMessage(), ex.getCause());
         return "error";
     }
 }

解説
- 1つ目のメソッドは,ToDoアプリのアプリケーション例外をキャッチする
-- アプリ内で想定している例外
- 2つ目のメソッドは,それ以外の任意の例外をキャッチする
-- アプリでは想定していない例外
- サンプルでは,エラーページに例外オブジェクトを渡し,ページ内でex.messageを表示している
--- もっと丁寧にやるには,エラーコードに応じて,適切なエラーメッセージをセットしてやる
 String message;
 switch (ex.getCode()) {
 case 101:
     message = "メンバーが存在しません"; break;
 case 102:
     message = "そのメンバーIDは既に使われています"; break;
 ...
 }

*** エラー画面 - HTMLテンプレート [#ad09c77a]
- resources/templates/error.html
 <!DOCTYPE html>
 <html lang="ja" xmlns:th="http://www.thymeleaf.org">
 
 <head>
     <meta charset="UTF-8">
     <title>エラー</title>
 </head>
 
 <body>
     <h1>エラー</h1>
 
 
      <img th:src="@{/img/todo_error.png}" width="320px"> <br/>
      
      <h3>
         [[${advice}]]         
      </h3>
     
     <p style="color:red">
         [[${exception.message}]]
     </p>
     
     <input type="button" onclick="history.back()" value="戻る" />
 </body>
 
 </html>

*** 画像 [#l2d070d8]
- resources/static/img/todo_error.png
-- &attachref(./todo_error.png,50%);

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS