Spring Boot處理全局統一異常的兩種方法與區別

https://www.jb51.net/article/162919.htm

前言

在後端發生異常或者是請求出錯時,前端通常顯示如下

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Jun 07 15:38:07 CST 2019
There was an unexpected error (type=Not Found, status=404).
No message available

對於用戶來說非常不友好。

本文主要講解如何在SpringBoot應用中使用統一異常處理。

實現方式

  • 第一種:使用@ControllerAdvice和@ExceptionHandler註解
  • 第二種: 使用ErrorController類來實現。

第一種:使用@ControllerAdvice和@ExceptionHandler註解

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@Slf4j

@ControllerAdvice

public class GlobalExceptionHandler {

 

 @ResponseBody

 @ExceptionHandler(NullPointerException.class)

 public BaseResult globalException(HttpServletResponse response,NullPointerException ex){

 

 

 log.info("GlobalExceptionHandler...");

log.info("錯誤代碼:" + response.getStatus());

BaseResult result = new WebResult(WebResult.RESULT_FAIL,"request error:"+response.getStatus()

     ,"GlobalExceptionHandler:"+ex.getMessage());

 return result;

}

 

}

註解@ControllerAdvice表示這是一個控制器增強類,當控制器發生異常且符合類中定義的攔截異常類,將會被攔截。

可以定義攔截的控制器所在的包路徑

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component

public @interface ControllerAdvice {

 @AliasFor("basePackages")

 String[] value() default {};

 

 @AliasFor("value")

 String[] basePackages() default {};

 

 Class<?>[] basePackageClasses() default {};

 

 Class<?>[] assignableTypes() default {};

 

 Class<? extends Annotation>[] annotations() default {};

}

註解ExceptionHandler定義攔截的異常類

1

2

3

4

5

6

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface ExceptionHandler {

 Class<? extends Throwable>[] value() default {};

}

第二種: 使用ErrorController類來實現。

系統默認的錯誤處理類爲BasicErrorController,將會顯示如上的錯誤頁面。

這裏編寫一個自己的錯誤處理類,上面默認的處理類將不會起作用。

getErrorPath()返回的路徑服務器將會重定向到該路徑對應的處理類,本例中爲error方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Slf4j

@RestController

public class HttpErrorController implements ErrorController {

 

 private final static String ERROR_PATH = "/error";

 

 @ResponseBody

 @RequestMapping(path = ERROR_PATH )

 public BaseResult error(HttpServletRequest request, HttpServletResponse response){

 log.info("訪問/error" + " 錯誤代碼:" + response.getStatus());

 BaseResult result = new WebResult(WebResult.RESULT_FAIL,"HttpErrorController error:"+response.getStatus());

return result;

 }

 @Override

 public String getErrorPath() {

 return ERROR_PATH;

 }

}

測試

以上定義了一個統一的返回類BaseResult,方便前端進行處理。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

package com.microblog.common.result;

 

import java.io.Serializable;

 

 

public class BaseResult implements Serializable {

 

 private static final long serialVersionUID = 1L;

 

 public static final int RESULT_FAIL = 0;

 public static final int RESULT_SUCCESS = 1;

 

 //返回代碼

 private Integer code;

 

 //返回消息

 private String message;

 

 //返回對象

 private Object data;

 

 public BaseResult(Integer code, String message) {

  this.code = code;

  this.message = message;

 }

 

 public BaseResult(Integer code, String message, Object object) {

  this.code = code;

  this.message = message;

  this.data = object;

 }

 

 

 public Integer getCode() {

  return code;

 }

 

 public void setCode(Integer code) {

  this.code = code;

 }

 

 public String getMessage() {

  return message;

 }

 

 public void setMessage(String message) {

  this.message = message;

 }

 

 public Object getData() {

  return data;

 }

 

 public void setData(Object data) {

  this.data = data;

 }

}

編寫一個測試控制器

1

2

3

4

5

6

7

8

9

10

11

12

13

@Slf4j

@RestController

@RequestMapping("/user")

public class TestController {

 

 @RequestMapping("/info1")

 public String test(){

  log.info("/user/info1");

 

  throw new NullPointerException("TestController have exception");

 

 }

}

1.發出一個錯誤的請求,也就是沒有對應的處理類。

從返回可以看到是由HttpErrorController類處理

1

{"code":0,"message":"HttpErrorController error:404","data":null}

2.發出一個正常的請求(TestController的test()處理),處理類中拋出空異樣

從返回中可以看出是由GlobalExceptionHandler類處理

1

{"code":0,"message":"request error:200","data":"GlobalExceptionHandler:TestController have exception"}

區別

1.註解@ControllerAdvice方式只能處理控制器拋出的異常。此時請求已經進入控制器中。

2.類ErrorController方式可以處理所有的異常,包括未進入控制器的錯誤,比如404,401等錯誤

3.如果應用中兩者共同存在,則@ControllerAdvice方式處理控制器拋出的異常,類ErrorController方式未進入控制器的異常。

4.@ControllerAdvice方式可以定義多個攔截方法,攔截不同的異常類,並且可以獲取拋出的異常信息,自由度更大。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章