首頁 > 軟體

springboot處理異常的5種方式

2022-08-04 14:01:23

程式的異常:Throwable

嚴重錯誤問題:Error     我們不處理。這種問題一般都是很嚴重的,我們一般處理不了,比如說記憶體溢位。

問題:Exception

1.執行期問題:RuntimeException            這種問題我們也不處理,因為是你寫程式碼的問題,而且這個問題的出現肯定是我們的程式碼不夠嚴謹,需要修正程式碼的。

2.編譯期問題:不是RuntimeException的異常     必須進行處理的,因為你不處理,編譯就不能通過。

如果程式出現了問題,我們沒有做任何處理,最終JVM會做出預設的處理。
1.把異常的名稱、原因及出現的位置等資訊輸出在控制檯。
2.同時會結束程式。
(但是呢,其餘沒有問題的程式就不能繼續執行了)
所以感覺JVM的預設處理不夠好,既然不好那我們就自己來處理唄。

1、自定義錯誤頁面

SpringBoot預設的例外處理機制:springboot預設提供了一套處理異常的機制。一旦程式出現了異常,SpringBoot會向/error的url傳送請求。在springboot中提供了一個叫BasicErrorController 來處理/error 請求,然後跳轉到預設顯示異常的頁面來展示異常資訊。
如 果 我 們 需 要 將 所 有 的 異 常 統一 跳 轉 到 自 定 義 的 錯 誤 頁 面 , 需 要 再
src/main/resources/templates 目錄下建立 error.html 頁面。注意:名稱必須叫 error

還可以在src/main/resources/templates/error目錄下編寫狀態碼.html檔案,會預設先從這裡找,找不到再找src/main/resources/templates下的error.html

2、@ExceptionHandle 註解處理異常

上一種方法不管發生什麼異常,都只能跳轉到一個頁面,顆粒度太大,這一種方式可以實現對不同的異常做不同的處理。

@RequestMapping
@Controller
public class ExceptionController {

    @PostMapping("/exception")
    public String hello(){
        //int i = 1/0;
        return "index";
    }

    /**
     * 該方法返回ModelAndView:目的是為了可以讓我們封裝檢視和錯誤資訊
     * @param e 引數 Exception e:會將產生異常物件注入到方法中
     * @return
     */
    @ExceptionHandler(value = {java.lang.ArithmeticException.class})
    public ModelAndView arithmeticExceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e);
        mv.setViewName("error");
        return mv;
    }
}

優點:可以自定義儲存異常資訊的key,和跳轉檢視的名稱。

缺點:需要編寫大量的異常方法,不能跨controller,如果兩個controller中出現同樣的異常,需要重新編寫例外處理方法。

3、@ControllerAdvice+@ExceptionHandler 註解處理異常

上一種方式必須要在每一個Controler裡面重複寫例外處理程式碼,程式碼複用性太差,這一種方法可以實現異常的全域性處理。需要建立一個能夠處理異常的全域性異常類。在該類上需要新增@ControllerAdvice 註解

/**
 * 全域性例外處理類
 */
@ControllerAdvice
public class GlobalController {

    /**
     * 該方法返回ModelAndView:目的是為了可以讓我們封裝檢視和錯誤資訊
     * @param e 引數 Exception e:會將產生異常物件注入到方法中
     * @return
     */
    //攔截的異常可以寫Exception
    @ExceptionHandler(value = {java.lang.ArithmeticException.class})
    public ModelAndView arithmeticExceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e+"controllerAdvice");
        mv.setViewName("error");
        return mv;
    }
}

缺點:編寫大量的例外處理方法,程式碼冗餘。

4、設定 SimpleMappingExceptionResolver 處理異常

上一種方式,每處理一種異常就要寫一個處理方法,如果有很多異常需要處理,寫起來會很麻煩,這一種方式可以很好的解決這種問題,需要在全域性異常類中新增一個方法完成異常的統一處理。

/**
 * 通過 SimpleMappingExceptionResolver 做全域性例外處理
 */
@Configuration
public class GlobalException {

    /**
     * 該方法必須要有返回值。返回值型別必須是: SimpleMappingExceptionResolver
     * @return
     */
    @Bean
    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();

        //引數1:異常的全類名  引數2:檢視的名字
        prop.setProperty("java.lang.ArithmeticException","error");
        prop.setProperty("java.lang.NullPointerException","error");
        //設定異常與檢視的對映資訊
        resolver.setExceptionMappings(prop);
        return resolver;
    }
}

缺點:不顯示具體異常資訊

5、自定義 HandlerExceptionResolver 類處理異常

上一種方式不能在跳轉頁面的同時攜帶異常資訊,這樣不利於排錯,當前這種方式可以解決上述問題,我們需 要 在全域性例外處理類中實現HandlerExceptionResolver 介面。

/**
 * 通過實現 HandlerExceptionResolver 介面做全域性例外處理
 */
@Configuration
public class GlobalException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView mv = new ModelAndView();
        //判斷不同的異常型別跳轉不同檢視
        if(ex instanceof ArithmeticException){
            mv.setViewName("error");
        }
        if(ex instanceof NullPointerException){
            mv.setViewName("error");
        }
        mv.addObject("errorMsg",ex.toString());

        return mv;
    }
}

通用例外處理:

1、自定義異常列舉類

public enum ExceptionEnum {
    //列舉常數
    PRICE_CANNOT_BE_NULL(500,"商品價格不能為空"),
    ;
    private int code;  //狀態碼
    private String msg; //異常資訊

    ExceptionEnum() {
    }

    ExceptionEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

2、自定義異常類

/**
 * 自定義異常類,繼承RuntimeException
 */
public class MyException extends RuntimeException{
    private ExceptionEnum exceptionEnum;

    public MyException() {
    }

    public MyException(ExceptionEnum exceptionEnum) {
        this.exceptionEnum = exceptionEnum;
    }

    public ExceptionEnum getExceptionEnum() {
        return exceptionEnum;
    }

    public void setExceptionEnum(ExceptionEnum exceptionEnum) {
        this.exceptionEnum = exceptionEnum;
    }

    @Override
    public String toString() {
        return "MyException{" +
                "exceptionEnum=" + exceptionEnum +
                '}';
    }
}

3、自定義異常結果處理類

/**
 * 自定義異常結果處理類
 */
public class ResultException {

    private Integer statusCode; //狀態碼
    private String message;     //異常資訊
    private Long timeStamp; //時間戳

    public ResultException() {
    }

    public ResultException(ExceptionEnum em){
        this.statusCode = em.getCode();
        this.message = em.getMsg();
        this.timeStamp = System.currentTimeMillis();
    }

    public Integer getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(Integer statusCode) {
        this.statusCode = statusCode;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Long getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(Long timeStamp) {
        this.timeStamp = timeStamp;
    }

    @Override
    public String toString() {
        return "ResultException{" +
                "statusCode=" + statusCode +
                ", message='" + message + ''' +
                ", timeStamp=" + timeStamp +
                '}';
    }
}

4、全域性例外處理

/**
 *  @ControllerAdvice + @ExceptionHandler +自定義異常  來做全域性例外處理
 */
@ControllerAdvice
public class GlobalException {

    /**
     * 攔截自定義異常MyException
     * @param e
     * @return
     */
//    @ExceptionHandler(MyException.class)
//    public @ResponseBody ResultException handlerRuntimeException(MyException e){
//        ExceptionEnum exceptionEnum = e.getExceptionEnum();
//        ResultException res = new ResultException(exceptionEnum);
//        

到此這篇關於springboot處理異常的5種方式的文章就介紹到這了,更多相關springboot處理異常內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com