如何優雅的處理異常?SpringBoot全局異常與數據校驗

要思考的問題前端

在如今的先後端交互中,一般都規範了接口返回方式,如返回的接口狀態(成功|失敗)以及要返回的數據在那個字段取,或者說失敗了之後提示信息從接口哪裏返回,所以,若是想作全局異常,而且異常發生後能準確的返回給前端解析,那麼須要異常發生時返回給前端的格式與正常失敗場景的格式一致。程序員

項目創建web

利用idea 工具,很容易的搭建一個SpringBoot項目,要引入的maven依賴以下:spring

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-validation</artifactId>
複製代碼
<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>
複製代碼
<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>
複製代碼

很簡單,除了加入web功能還加入了咱們須要用到的JSR-303校驗框架。sql

定義成功失敗 返回碼後端

public class Code {架構

/**

 * 成功

 */

public static int SUCCESSED = 1;

/**

 * 失敗

 */

public static int FAILED = -1;
複製代碼

}併發

定義接口返回響應實體app

public class Response implements Serializable{框架

/**

* 

*/
複製代碼

private static final long serialVersionUID = 4250719891313555820L;

/**

* 返回結果集

*/
複製代碼

private T result;

/**

* 返回消息

*/
複製代碼

private String msg;

/**

* 響應碼

*/
複製代碼

private Integer code;

//set get 略

}

全局異常攔截和驗證

定義自定義業務異常

public class MyException extends RuntimeException {

private static final long serialVersionUID = -5875371379845226068L;

public MyException(){}

public MyException(String msg){

    this.msg = msg ;

}

/**

 * 異常信息

 */

private String msg ;

/**

 * 具體異常碼

 */

private int code = Code.FAILED;
複製代碼

get set 略

編寫全局異常控制器並對自定義異常作處理

@ControllerAdvice

public class GlobalExceptionHandler {

private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
複製代碼

@ExceptionHandler(value = MyException.class)

@ResponseBody

public Response myExceptionErrorHandler(MyException ex) throws Exception {

logger.error("myExceptionErrorHandler info:{}",ex.getMessage());

Response<String> r = new Response<>();

r.setMsg(ex.getMsg());

r.setCode(ex.getCode());

return r;
複製代碼

}

編寫controller模擬拋出業務異常

@RestController

@RequestMapping("/user")

public class UserController {

@PostMapping(value = "/update")

Response update(User user){

//todo 此處爲模擬異常拋出

if(true){

    throw new MyException("更新失敗");

}

//todo 此處爲模擬返回

Response<Boolean> response = new Response<>();

response.setCode(Code.SUCCESSED);

response.setResult(true);

return  response;
複製代碼

}

}

postMan模擬請求接口,進行驗證

數據綁定異常處理

一般咱們操做數據的時候,不只前端須要進行數據校驗,後端也應當進行攔截和進行相應的錯誤提示,JSR-303校驗框架也是咱們的一種選擇。

編寫實體User,並對屬性進行註解控制

public class User {

@NotNull(message = "用戶名不能爲空")

private String userName;

private  int age;
複製代碼

//...

全局異常控制類加入攔截

@ControllerAdvice

public class GlobalExceptionHandler {

private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

 @ExceptionHandler(value = BindException.class)

 @ResponseBody

 public Response<String> bindExceptionErrorHandler(BindException ex) throws Exception {

      logger.error("bindExceptionErrorHandler info:{}",ex.getMessage());

      Response<String> r = new Response<>();

      StringBuilder sb = new StringBuilder();

      FieldError fieldError = ex.getFieldError();

      sb.append(fieldError.getDefaultMessage());

      r.setMsg(sb.toString());

      r.setCode(Code.FAILED);

      return r;

 }
複製代碼

//...

編寫控制器

@RestController

@RequestMapping("/user")

public class UserController {

@PostMapping(value = "/add")

Response<User> add(@Validated User user){

    //todo 此處爲模擬返回

    Response<User> response = new Response<>();

    response.setCode(Code.SUCCESSED);

    response.setResult(new User());

    return  response;

}
複製代碼

//...

postMan模擬請求

不填寫任何屬性,模擬添加操做,準確進行攔截和報錯

項目結構預覽:

結尾

適合的纔是最好的,每一個團隊都應摸索出本身的一套異常解決方案,本文所提僅針對業務異常,但願你們也能有所收穫

歡迎工做一到五年的Java工程師朋友們加入Java程序員開發: 854393687

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索