補充
springboot中也是一樣的可以對結果進行統一格式的包裝,這樣也就方便了前台的統一接收處理了;
1.結果集包裝類

package com.example.demo.bean; /** * 結果包裝 * * @author zcc ON 2018/2/9 **/ public class Result<T> { /** * 錯誤代碼(可以設定例如500表示錯誤) */ private Integer code; /** * 提示信息 */ private String msg; /** * 數據內容 */ private T data; public Result() { } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
可以參考之前SSM中的包裝類:http://www.cnblogs.com/jiangbei/p/7080955.html
2.使用包裝結果集
@PostMapping(value = "/girls") public Result<Girl> addGirl(@Valid Girl girl, BindingResult bindingResult) { Result<Girl> result = new Result<>(); // 表單驗證邏輯
if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); StringBuffer sb = new StringBuffer(); for (FieldError fieldError : fieldErrors) { sb.append(fieldError.getDefaultMessage()); } result.setCode(500); result.setMsg(sb.toString()); return result; } result.setCode(200); result.setMsg("success"); result.setData(girlRepository.save(girl)); return result; }
3。改進結果集
通過代碼觀察或者對比SSM中的示例,都發現這樣寫在代碼中是挺傻的,這樣,我們提供一個工具類(或者在結果集中直接封裝)
/** * 結果集的工具類 * * @author zcc ON 2018/2/9 **/
public class ResultUtils { public static Result<Object> success(Object data) { Result<Object> result = new Result<>(); result.setCode(200); result.setMsg("success"); result.setData(data); return result; } public static Result<Object> error(String msg) { Result<Object> result = new Result<>(); result.setCode(500); result.setMsg(msg); return result; } }
使用:
@PostMapping(value = "/girls") public Result<Object> addGirl(@Valid Girl girl, BindingResult bindingResult) { // 表單驗證邏輯
if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); StringBuffer sb = new StringBuffer(); for (FieldError fieldError : fieldErrors) { sb.append(fieldError.getDefaultMessage()); } return ResultUtils.error(sb.toString()); } return ResultUtils.success(girlRepository.save(girl)); }
一、概述
springboot提供了默認的統一異常處理,basicErrorController,這個controller提供了默認了錯誤處理方法,包括錯誤跳轉的路徑和渲染方法。
因為默認的錯誤處理方法可能會不適合項目的需要,所以當需要自定義統一錯誤處理的時候,可以繼承basicErrorController。或重新實現basicErrorController.
統一異常處理可配置400,404,500等狀態異常錯誤處理。basicErrorController內部提供了針對accept=**的不同處理方法,可區別是普通調用還是ajax等其他調用。
缺點:需要重寫basicErrorController。並配置覆蓋原來springboot的默認配置。當使用EmbeddedServletContainerCustomizer類配置400,404。500的時候,暫時不清楚調用springboot的處理方法。
二、問題提出
假設需要根據girl的不同age作出不同的動作,controller如下:
@GetMapping(value = "/girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) { // 判斷應該交給service
service:
public void getAge(Integer id) { Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小學生
} else { // 上初中了
} }
如果只是簡單的判斷,不同年齡返回不同信息給前台,那確實可以通過返回一個String來進行
但是,如果業務比較復雜,需要的不僅僅是返回一個字符串,而是需要其他動作,這個時候就顯得有點力不從心了!
三、統一異常處理
1.基本用法
controller調用service,拋出異常即可:
@GetMapping(value = "/girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) throws Exception{ // 判斷應該交給service
girlService.getAge(id); }
service也是,該拋異常就拋出異常:
public void getAge(Integer id) throws Exception{ Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小學生
throw new Exception("小學生!"); } else { // 上初中了
throw new Exception("初中生!"); } }
統一異常處理類:
package com.example.demo.handle; import com.example.demo.bean.Result; import com.example.demo.utils.ResultUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * 異常處理類 * 添加@ControllerAdvice標記為異常處理類 * @author zcc ON 2018/2/9 **/ @ControllerAdvice public class MyExceptionHandler { /** * 如果不在這里加@ResponseBody,則需要在類上加 * @param e 異常 * @return
*/ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e) { return ResultUtils.error(e.getMessage()); } }
2.自定義異常
寫自定義異常還是之前的基礎篇的老套路,基本就是幾個構造方法的編寫,再根據需要加上自己的變量!
package com.example.demo.exception; /** * 自定義異常 * 繼承RuntimeException才能使得spring進行異常時的回滾 * @author zcc ON 2018/2/9 **/
public class MyException extends RuntimeException{ private Integer code; public MyException(Integer code, String msg) { super(msg); this.code = code; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
異常處理類:
package com.example.demo.handle; import com.example.demo.bean.Result; import com.example.demo.exception.MyException; import com.example.demo.utils.ResultUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * 異常處理類 * 添加@ControllerAdvice標記為異常處理類 * @author zcc ON 2018/2/9 **/ @ControllerAdvice public class MyExceptionHandler { /** * 如果不在這里加@ResponseBody,則需要在類上加 * @param e 異常 * @return
*/ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e) { // 先判斷捕獲的是不是我們定義的異常
if (e instanceof MyException) { MyException me = (MyException) e; return ResultUtils.exp(me.getCode(), me.getMessage()); } else { return ResultUtils.error("未知錯誤!"); } } }
其他地方需要注意:
既然MyException繼承RuntimeException了,那controller和service就不用拋出異常了
ResultUtils根據需要微調一些
統一404、500異常處理
@ExceptionHandler(value = Exception.class) @ResponseBody public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { logger.error("", e); ResponseData r = new ResponseData(); r.setMessage(e.getMessage()); if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) { r.setCode(404); } else { r.setCode(500); }
三、使用枚舉優化管理
1.枚舉
package com.example.demo.enums; /** * 結果集的枚舉管理類 * 不用給出setter了,因為枚舉不會再去set了 * @author zcc **/
public enum ResultEnum { UNKNOWN(-1, "未知錯誤"), SUCCESS(200, "success"), PRIMARY(100, "小學生"), MIDDLE(101, "中學生"); private Integer code; private String msg; ResultEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; } }
更多枚舉基礎知識,參考:http://www.cnblogs.com/jiangbei/p/7580482.html
2.調整自定義異常的構造方法
/** * 自定義異常 * 繼承RuntimeException才能使得spring進行異常時的回滾 * @author zcc ON 2018/2/9 **/
public class MyException extends RuntimeException{ private Integer code; public MyException(ResultEnum resultEnum) { super(resultEnum.getMsg()); this.code = resultEnum.getCode(); } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
3.使用自定義枚舉統一管理錯誤代碼和錯誤信息之間的關系
public void getAge(Integer id) { Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小學生
throw new MyException(ResultEnum.PRIMARY); } else { // 上初中了
throw new MyException(ResultEnum.MIDDLE); } }