概要
你是不是在為業務邏輯中出現的異常弄的焦頭爛額,常常在后台報錯,前端卻無法提示錯誤內容,導致用戶體驗極差?比如下單失敗,前端只能提示下單失敗,但是卻不知道為什么失敗,是庫存不足,還是余額不足,亦或是商品已經失效?
之前想在 service 層直接返回封裝好的 Reponse(code, data,msg) 對象,這樣的話我就直接在service層提示出錯原因了(msg:錯誤提示),但是這樣代碼就不夠美觀,因為Response原本是設計為后端統一返回的對象,太臃腫,最后決定用自定義異常來完成。
定義常見的錯誤枚舉類
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author: zp
* @Date: 2019-10-10 14:47
* @Description:
*/
@Getter
@AllArgsConstructor
public enum ErrorType {
/**
* 錯誤類型
*/
OBJECT_NOT_FOUND(0,"對象不存在"),
INVALID_PARAMS(1,"參數不正確"),
result_not_exist(2,"記錄不存在")
;
/**
* 錯誤碼
*/
private int code;
/**
* 提示信息
*/
private String msg;
}
自定義異常
提供了兩個構造方法,一個用來提示常見的錯誤(枚舉類中的),另一個提示不常用的(一次兩次的那種),可拓展。
import com.example.demojpa.enums.ErrorType;
import lombok.Getter;
/**
* @author: zp
* @Date: 2019-10-10 14:42
* @Description:
*/
@Getter
public class ServiceException extends RuntimeException{
private Integer code;
/**
* 使用已有的錯誤類型
* @param type 枚舉類中的錯誤類型
*/
public ServiceException(ErrorType type){
super(type.getMsg());
this.code = type.getCode();
}
/**
* 自定義錯誤類型
* @param code 自定義的錯誤碼
* @param msg 自定義的錯誤提示
*/
public ServiceException(Integer code, String msg){
super(msg);
this.code = code;
}
}
定義響應對象及工具類(這個不是必需的)
-
響應對象
/** * @author: zp * @Date: 2019-10-10 15:22 * @Description: */ @Data public class Response<T> { /** * 狀態碼 */ private Integer code; /** * 請求成功時返回的對象 */ private T data; /** * 提示信息 */ private String msg; }
-
工具類
import com.example.demojpa.model.Response; /** * @author: zp * @Date: 2019-10-10 15:48 * @Description: */ public class ResponseUtils { /** * 調用成功 */ private static final String SUCCESS = "調用成功!"; public static Response success(Object obj){ Response res = new Response(); res.setCode(200); res.setData(obj); res.setMsg(SUCCESS); return res; } public static Response success(){ return success(null); } public static Response error(Integer code, String msg){ Response res = new Response(); res.setCode(code); res.setMsg(msg); return res; } }
異常處理類
import com.example.demojpa.exception.ServiceException;
import com.example.demojpa.model.Response;
import com.example.demojpa.utils.ResponseUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author: zp
* @Date: 2019-10-10 15:11
* @Description:
*/
@ControllerAdvice
public class ServiceExceptionHandler {
/**
* @ExceptionHandler相當於controller的@RequestMapping
* 如果拋出的的是ServiceException,則調用該方法
* @param se 業務異常
* @return
*/
@ExceptionHandler(ServiceException.class)
@ResponseBody
public Response handle(ServiceException se){
return ResponseUtils.error(se.getCode(),se.getMessage());
}
}
測試
為了簡單一點,我直接在controller中拋異常,看看結果。
@GetMapping("/exception/{msg}")
public String exception(@PathVariable String msg) throws InvalidParamExceptionAbstract, NoSuchObjectExceptionAbstract {
if(StringUtils.isEmpty(msg)){
throw new ServiceException(ErrorType.INVALID_PARAMS);
}else if("null".equals(msg)) {
throw new ServiceException(ErrorType.OBJECT_NOT_FOUND);
}else{
throw new ServiceException(250,"瞧你那傻樣!");
}
}
關注我不會讓你失望喲~