網頁

2019/12/23

Spring Boot @ControllerAdvice用法

本篇介紹Spring Boot/Spring Web MVC的@ControllerAdvice annotation的用法。


@ControllerAdvice是在Spring 3.2新增的annotation,可以用來攔截並處理應用程式中全部Controller所拋出的Exception例外錯誤。其也是@Component,所以會被Spring scan為Bean。

以下是@ControllerAdvice的簡單範例。

環境如下:

  • macOS High Sierra
  • Java 1.8
  • IntelliJ IDEA 2019.2.1(Community Edition)
  • Spring Boot 2.1.3.RELEASE

首先建立一個Spring Boot專案 (Eclipse參考, IntelliJ IDEA參考)。

Spring Boot專案配置檔application.properties設定如下。

application.properties

#context path
server.servlet.context-path=/demo
#port
server.port=8080

所以應用程式在本機的連結路徑為http://localhost:8080/demo


新增一個自訂的Exception類DemoException,繼承RuntimeException。此例外類別待會測試時會被拋出並被下面的DemoExceptionHandler處理。

DemoException

package com.abc.demo.exception;

public class DemoException extends RuntimeException {

    private String errorCode;
    private String errorMessage;

    public DemoException(String errorCode, String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    // getters and setters
}

新增一個用來處理應用程式例外的類別DemoExceptionHandler,在類別名稱前掛上@ControllerAdvice注釋,因此應用程式拋出的所有例外都可被此類別攔截。

DemoExceptionHandler中定義一個方法,在方法前掛上@ExceptionHandler ,其value設為DemoException.class,則此方法即可處理被拋出的DemoException

DemoExceptionHandler

package com.abc.demo.exception.handler;

import com.abc.demo.exception.DemoException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class DemoExceptionHandler {

    @ExceptionHandler({DemoException.class}) // <-- 
    public final void handleDemoException(DemoException ex) {
        System.out.println("handle DemoException...");
        System.out.println("error code:" + ex.getErrorCode());
        System.out.println("error message:" + ex.getErrorMessage());
    }
    // by 菜鳥工程師肉豬
}

最後建立一個DemoController類用用來測試DemoExceptionHandler處理例外的效果。

DemoController.hello()被調用時會直接拋出DemoException
DemoController.getMessagesByDate()如果輸入參數非定義的日期格式也會拋出DemoException

DemoController

package com.abc.demo.controller;

import com.abc.demo.exception.DemoException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@RestController
public class DemoController {

    @GetMapping("/hello")
    public String hello() {
        System.out.println("hello");
        throw new DemoException("9999", "test");

    }

    @GetMapping("/message/{dateStr}")
    public List<String> getMessagesByDate(@PathVariable String dateStr) {
        System.out.println(dateStr);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new DemoException("1003", "wrong format");
        }

        // 其他邏輯 by 菜鳥工程師肉豬
        return new ArrayList<>();

    }

}

接著啟動專案,在瀏覽器位址輸入http://localhost:8080/demo/hello來發出請求給DemoController.hello()。該方法內拋出的DemoException會由DemoExceptionHandler.handleDemoException()處理,所以會在console印出以下結果。

hello
handle DemoException...
error code:9999
error message:test

在瀏覽器位址輸入http://localhost:8080/demo/message/201901231來發出請求給DemoController.getMessageByDate()。由於傳入的日期格式不符pattern,所以會先拋出ParseException並被try catch捕捉,然後才拋出自訂的DemoException,最後由DemoExceptionHandler.handleDemoException()處理,所以會在console印出以下結果。

201901231
handle DemoException...
error code:1003
error message:wrong format

專案src/main目錄結構如下。




沒有留言:

張貼留言