這篇學習筆記是Spring系列筆記的第7篇,該筆記是筆者在學習黑馬程序員SSM框架教程課程期間的筆記,供自己和他人參考。
Spring學習筆記目錄
筆記1:【SSM】Spring基礎: IoC配置學習筆記-CSDN博客?對應黑馬課程P1~P20的內容。
筆記2: 【SSM】Spring學習筆記2:注解配置bean_ssm黑馬筆記-CSDN博客?對應黑馬課程P21~P27
筆記3:?【SSM】Spring學習筆記3:Spring整合MyBatis和Junit_spring整合mybaits-CSDN博客 對應黑馬課程P28~30
筆記4:【SSM】Spring學習筆記4:Spring的AOP編程-CSDN博客?對應黑馬課程P31~39
筆記5:【SSM】Spring學習筆記5:Spring事務-CSDN博客?對應黑馬課程P40~42
筆記6: 【SSM】SpringMVC學習筆記6:SpringMVC入門-CSDN博客?對應黑馬課程P43~58
筆記7: 此篇?對應黑馬課程P59~65
筆記8:【SSM】SpringMVC學習筆記8:攔截器-CSDN博客?對應黑馬課程P71~74
筆記9:【SSM】SpringBoot學習筆記1:SpringBoot快速入門-CSDN博客?對應黑馬課程P90~101
1.表現層與前端的數據傳輸協議
一般將需要傳遞的數據,封裝成一個統一的格式。
如下的一種協議規定:data封裝要傳輸的數據,code標記傳遞的數據類型/以及操作是否成功的狀態,msg傳輸操作失敗時候傳輸的信息。
該協議不固定,主要由前后端人員協調好。
public class Result {private Object data;private Integer code;private String msg;public Result() {}public Result(Integer code,Object data) {this.data = data;this.code = code;}public Result(Integer code, Object data, String msg) {this.data = data;this.code = code;this.msg = msg;}//所有屬性得到getter/setter方法和toString()
}
狀態碼code用一個枚舉類來維護。
public class Code {public static final Integer SAVE_OK = 20011;public static final Integer DELETE_OK = 20021;public static final Integer UPDATE_OK = 20031;public static final Integer GET_OK = 20041;public static final Integer SAVE_ERR = 20010;public static final Integer DELETE_ERR = 20020;public static final Integer UPDATE_ERR = 20030;public static final Integer GET_ERR = 20040;public static final Integer SYSTEM_ERR = 50001;public static final Integer SYSTEM_TIMEOUT_ERR = 50002;public static final Integer SYSTEM_UNKNOW_ERR = 59999;public static final Integer BUSINESS_ERR = 60002;
}
在controller類里面返回的數據類型統一成result
@RestController
@RequestMapping("/books")
public class BookController {@Autowiredprivate BookService bookService;@PostMappingpublic Result save(@RequestBody Book book) {boolean flag = bookService.save(book);return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);}@PutMappingpublic Result update(@RequestBody Book book) {boolean flag = bookService.update(book);return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);}@DeleteMapping("/{id}")public Result delete(@PathVariable Integer id) {boolean flag = bookService.delete(id);return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);}@GetMapping("/{id}")public Result getById(@PathVariable Integer id) {Book book = bookService.getById(id);Integer code = book != null ? Code.GET_OK : Code.GET_ERR;String msg = book != null ? "" : "數據查詢失敗,請重試!";return new Result(code,book,msg);}@GetMappingpublic Result getAll() {List<Book> bookList = bookService.getAll();Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;String msg = bookList != null ? "" : "數據查詢失敗,請重試!";return new Result(code,bookList,msg);}
}
2. 異常處理
2.1 常見異常的誘因
?
2.2 異常處理類
為了統一管理,異常可以層層上拋,拋到表現層(寫controller那一層)處理。
@RestControllerAdvice
聲明這個類是個異常處理類,注解@RestControllerAdvice用于全局性處理Controller拋出的異常。
@ExceptionHandler
用于方法上面,標注該方法用于處理什么類型的異常,注解參數接受異常類型。
異常處理之后要返回result信息,因為該異常是表現層處理的異常,而表現層直接和前端相連。返回的result最終會被前端接收。
//@RestControllerAdvice用于標識當前類為REST風格對應的異常處理器
//豆包:主要用于全局性地處理控制器(Controller)所拋出的異常,并且會直接返回 JSON、XML 這類格式的數據,而非視圖。
@RestControllerAdvice
public class ProjectExceptionAdvice {//@ExceptionHandler用于設置當前處理器類對應的異常類型@ExceptionHandler(SystemException.class)public Result doSystemException(SystemException ex){//具體的異常處理……return new Result(ex.getCode(),null,ex.getMessage());}
}
2.3 項目異常處理*
2.3.1 異常分類
項目中的異常可以分為下三種異常,實際情況根據具體情況來定
?
2.3.2 自定義異常
針對自己對項目劃分的異常種類,自定義異常
自定義的異常需要繼承自已有的異常類型。需要為自定義異常提供構造器(根據需要)。自定義異常中自定義屬性code,需要提供get方法和set方法。
業務異常
//自定義異常處理器,用于封裝異常信息,對異常進行分類
public class BusinessException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public BusinessException(Integer code, String message) {super(message);this.code = code;}public BusinessException(Integer code, String message, Throwable cause) {super(message, cause);this.code = code;}
系統異常
public class SystemException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public SystemException(Integer code, String message) {super(message);this.code = code;}public SystemException(Integer code, String message, Throwable cause) {super(message, cause);this.code = code;}}
2.3.4 處理自定義異常
在異常處理類中對三種異常分別處理。其中resule返回的信息從異常對象中獲取。
@RestControllerAdvice
public class ProjectExceptionAdvice {//@ExceptionHandler用于設置當前處理器類對應的異常類型@ExceptionHandler(SystemException.class)public Result doSystemException(SystemException ex){//記錄日志//發送消息給運維//發送郵件給開發人員,ex對象發送給開發人員return new Result(ex.getCode(),null,ex.getMessage());}@ExceptionHandler(BusinessException.class)public Result doBusinessException(BusinessException ex){return new Result(ex.getCode(),null,ex.getMessage());}//除了自定義的異常處理器,保留對Exception類型的異常處理,用于處理非預期的異常@ExceptionHandler(Exception.class)public Result doOtherException(Exception ex){//記錄日志//發送消息給運維//發送郵件給開發人員,ex對象發送給開發人員return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系統繁忙,請稍后再試!");}
}
2.3.5 使用自定義異常
系統遇到一個異常會不會自動識別成自定義異常,需要在異常可能出現的地方手動包裝成自定義異常。
public Book getById(Integer id) {//模擬業務異常,包裝成自定義異常if(id == 1){throw new BusinessException(Code.BUSINESS_ERR,"業務異常");}//模擬系統異常,將可能出現的異常進行包裝,轉換成自定義異常try{int i = 1/0;}catch (Exception e){throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服務器訪問超時,請重試!",e);}return bookDao.getById(id);
}