做爲一個程序員,雖然技術不厲害,可是都有一個向上的心,原來一直負責業務開發,梳理業務、設計流程、開發代碼,最近開始接觸一些架構類的設計和思路java
全國醫改在即,項目組接了一個醫療改革相關的供應商項目,主要是針對物流方向的。程序員
技術架構:領導要求用springcloud可是新來的成員都沒有相關開發經驗,項目負責人直接在網上扒了一套微服務的代碼(我的感受不太成熟),好多東西不太全,web
因此須要從新整理,因爲項目負責人比較忙,本身有迫切的想要了解一些東西,因此針對架構層次的代碼學習了一下,spring
本身原來只作業務,從不關心架構的設計是否合理優美,甚至在業務方向已經作到管理層次,後來跳槽離職後才發現本身技術的短板,因此一直在補充學習segmentfault
其實只須要架構師搭建微服務架構便可,項目組成員仍是針對不一樣的功能模塊進行業務開發,和原來的SSM沒有本質區別,只是增長了一些新的註解,和組件的使用後端
這裏就不對微服務的組件進行介紹了,只是針對本身部署的異常處理進行記錄——只是我的理解,若有好的設計歡迎指正架構
問題描述app
技術架構是先後端分離,想着統一返處理回值(包括正常結果和異常結果),可是架構代碼只是作了一個本身的返回類Map類型,以下前後端分離
package com.bootdo.clouddocommon.utils; import java.util.HashMap; import java.util.Map; public class R extends HashMap<String, Object> { private static final long serialVersionUID = 1L; public R() { put("code", 0); put("msg", "操做成功"); } public static R error() { return error(500, "操做失敗"); } public static R operate(boolean b){ if(b){ return R.ok(); } return R.error(); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map<String, Object> map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } public static R error401() { return error(401, "你尚未登陸"); } public static R error403() { return error(403, "你沒有訪問權限"); } public static R data(Object data){ return R.ok().put("data",data); } public static R page(Object page){ return R.ok().put("page",page); } @Override public R put(String key, Object value) { super.put(key, value); return this; } }
這種這種類封裝方式很好的處理的全部Controller類的返回結果 例如;dom
@Log("停用記錄") @ApiOperation(value = "停用信息記錄") @PutMapping("/stop") R stop(@RequestBody List<Long> idList) { return R.operate(consumeMaterialService.stop(idList,getUser()) > 0); }
@Log("獲取耗材信息列表(無分頁)") @ApiOperation(value = "獲取耗材信息列表(無分頁)") @ApiImplicitParam(name = "params", value = "map參數集合(基礎的參數格式——可在結構內增長其餘過濾條件字段)", example = "{consumeName:10}") @GetMapping("/allList") R list(@RequestParam Map<String, Object> params) { List<ConsumeMaterialDO> list = consumeMaterialService.list(params); return R.data(list); }
這種方式特色
一、很好的統一了Controller層的返回結果
二、沒有一套錯誤編碼和對應的信息,須要硬編碼的形式在代碼提現,例如:(該問題能夠經過增長一個錯誤信息的枚舉類來解決——下文中會說明)
R findMaterialBySupplierIdNotAddList(@RequestParam Map<String, Object> params){ if(params.isEmpty()){ return R.error("30032",」"醫院ID和供應商ID不能爲空");//能夠只寫錯誤信息,也能夠加上編碼 }else{ Long id=new Long(params.get("hospitalId").toString()); if(id==null||id==0){ return R.error("醫院ID不能爲空"); } Long sid=new Long(params.get("supplierId").toString()); if(sid==null||sid==0){ return R.error("供應商ID不能爲空"); } } //查詢列表數據 Query query = new Query(params); List<ConsumeMaterialDO> materialList = supplierService.findMaterialBySupplierIdNotAddList(query); int total = supplierService.findMaterialBySupplierIdNotAddCount(query); PageUtils pageUtils = new PageUtils(materialList, total); //返回狀態字典 List<SysDictDO> statusList = initDataService.getSysDictByType("status"); //返回耗材狀態 List<SysDictDO> measurementStatusList = initDataService.getSysDictByType("unit"); return R.ok().put("page",pageUtils).put("suppliermaterialstatusoptions",statusList).put("measurementstatusoptions",measurementStatusList); }
三、沒有辦法處理service層的異常返回,由於service 層返回的都是具體的實體或者整數
由於原來作過的項目中有過相關的異常處理——記得是定義一個統一的異常接收類對返回值結構進行處理,其餘地方直接拋出異常便可,固然須要定義一套錯誤信息枚舉類,用於統一返回信息內容
隨意根據本身的理解和經驗,查找相關代碼作了一套異常處理的代碼,代碼和原理很簡單
參考連接:http://www.javashuo.com/article/p-rqbccjeg-hx.html
一、首先在原來的基礎上增長一個錯誤信息的枚舉類——代碼比較多刪減了一部分,能夠根據本身的需求添加
package com.bootdo.clouddocommon.constants; /** * 異常處理狀態碼 */ public enum ResultCode { SUCCESS(0, "請求成功"), Unknown_Exception(-1, "未知異常"), USER_NOT_FOUND(10001, "沒有找到此用戶"), USERNAME_NOT_BLANK(10002, "用戶名不能爲空"), USERNAME_EXIST(10003, "用戶名已經存在"), USERTYPE_ERROR(100031, "用戶類型不正確"), DEVICE_ID_EMPTY(10052,"設備ID:deviceId不能爲空"), DELETE_CONNECT_ERROR(10053,"刪除connect出錯"); private int code; private String message; ResultCode(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } }
二、添加一個自定義的異常類用於拋出:主要是將本身的錯誤編碼和信息整合進去——原生的異常類也是能夠的,只是好像沒有自定的編碼返回(自定義的異常類也須要集成原生的異常類——紅色部分——有興趣的同窗能夠看一下源碼)
package com.bootdo.clouddoadmin.config; import com.bootdo.clouddocommon.constants.ResultCode; /** * 功能描述: <br> * 〈異常類封裝——定義拋出的異常類〉 * @return: * @since: 1.0.0 * @Author: * @Date: */ public class DomainException extends RuntimeException { private int errCode = ResultCode.Unknown_Exception.getCode(); public DomainException() { super(ResultCode.Unknown_Exception.getMessage()); } public DomainException(ResultCode resultCode) { super(resultCode.getMessage()); this.errCode = resultCode.getCode(); } public int getErrCode() { return errCode; } public void setErrCode(int errCode) { this.errCode = errCode; } }
三、添加統一的異常返回處理——RestControllerAdvice(ControllerAdvice)攔截異常並統一處理
package com.bootdo.clouddoadmin.config; import com.bootdo.clouddocommon.utils.R; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; /** * 功能描述: <br> * 〈統一異常處理返回〉 * @return: * @since: 1.0.0 * @Author: * @Date: */ @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = DomainException.class) public R domainExceptionHandler(HttpServletRequest req, DomainException e) throws Exception { e.printStackTrace(); return R.error(e.getErrCode(), e.getMessage()); } }
這樣總體就設計完了,不管是在service或者controller中均可以拋出異常,而後通過處理成爲統一格式的返回值
例如:
throw new DomainException(ResultCode.CODE_EMPTY);
經測試是有效的——結果截圖就再也不展現了