前言java
前段時間部門搭建新系統,須要出異常後統一接口的返回格式,因而用到了Spring的註解@RestControllerAdvice。如今把此註解的用法總結一下。web
用法spring
首先定義返回對象ResponseDtothis
1 package com.staff.points.common; 2 3 import lombok.Data; 4 5 import java.io.Serializable; 6 7 @Data 8 public class ResponseDto<T> implements Serializable { 9 private static final long serialVersionUID = -284719732991678911L; 10 11 private String code; 12 13 private String message; 14 15 private T data; 16 17 public static <T> ResponseDto<T> assemblingSuccessResponse(T data) { 18 ResponseDto<T> responseDto = new ResponseDto<>(); 19 responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 20 responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage()); 21 responseDto.setData(data); 22 return responseDto; 23 } 24 25 public static <T> ResponseDto<T> assemblingSuccessResponse() { 26 ResponseDto<T> responseDto = new ResponseDto<>(); 27 responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode()); 28 responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage()); 29 responseDto.setData(null); 30 return responseDto; 31 } 32 33 public static <T> ResponseDto<T> assemblingFailureResponse(ResponseCodeEnum data) { 34 ResponseDto<T> responseDto = new ResponseDto<>(); 35 responseDto.setCode(data.FAILURE.getCode()); 36 responseDto.setMessage(data.FAILURE.getMessage()); 37 return responseDto; 38 } 39 40 public static <T> ResponseDto<T> assemblingFailureResponse() { 41 ResponseDto<T> responseDto = new ResponseDto<>(); 42 responseDto.setCode(ResponseCodeEnum.FAILURE.getCode()); 43 responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage()); 44 return responseDto; 45 } 46 }
而後定義返回碼的枚舉類,此處只定義了兩種,有須要能夠往下添加不少。spa
1 package com.staff.points.common; 2 3 import lombok.AllArgsConstructor; 4 import lombok.Getter; 5 6 @AllArgsConstructor 7 @Getter 8 public enum ResponseCodeEnum { 9 SUCCESS("00", "成功"), 10 FAILURE("01", "系統異常"); 11 12 13 private String code; 14 private String message; 15 }
下面是自定義的異常類code
1 package com.staff.points.common; 2 3 import lombok.Data; 4 5 @Data 6 public class StaffPointsException extends RuntimeException{ 7 private String code; 8 private String message; 9 public StaffPointsException () {} 10 11 public StaffPointsException (Exception e) { 12 super(e); 13 } 14 15 public StaffPointsException (String code, String message) { 16 super(message); 17 this.code = code; 18 this.message = message; 19 } 20 21 public StaffPointsException (ResponseCodeEnum codeEnum) { 22 super(codeEnum.getMessage()); 23 this.code = codeEnum.getCode(); 24 this.message = codeEnum.getMessage(); 25 } 26 }
而後是關鍵的@RestControllerAdvice修飾的類對象
1 package com.staff.points.exception; 2 3 import com.staff.points.common.ResponseCodeEnum; 4 import com.staff.points.common.ResponseDto; 5 import com.staff.points.common.StaffPointsException; 6 import org.slf4j.Logger; 7 import org.slf4j.LoggerFactory; 8 import org.springframework.stereotype.Component; 9 import org.springframework.web.bind.annotation.ExceptionHandler; 10 import org.springframework.web.bind.annotation.RestControllerAdvice; 11 12 @RestControllerAdvice 13 @Component 14 public class UnifyExceptionHandler { 15 private Logger logger = LoggerFactory.getLogger(UnifyExceptionHandler.class); 16 17 @ExceptionHandler(Exception.class) 18 public ResponseDto handlerCommonException (Exception e) { 19 ResponseDto responseDto = new ResponseDto<>(); 20 responseDto.setCode(ResponseCodeEnum.FAILURE.getCode()); 21 responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage()); 22 logger.info("UnifyExceptionHandler.handlerCommonException exception:" + e); 23 return responseDto; 24 } 25 // 報StaffPointException時,對其進行攔截並處理的方法 26 @ExceptionHandler(StaffPointsException.class) 27 public ResponseDto handlerCustomizeException (StaffPointsException e) { 28 ResponseDto responseDto = new ResponseDto<>(); 29 responseDto.setCode(e.getCode()); 30 responseDto.setMessage(e.getMessage()); 31 logger.info("UnifyExceptionHandler.handlerCustomizeException StaffPointsException:" + e); 32 return responseDto; 33 } 34 }
運行代碼時,若是出現了StaffPointException,那麼就會被攔截進入第27行的方法(就是說能夠自由的在業務代碼裏往外throw自定義異常了);若是出現了其餘的異常,則進入18行的方法,統一返回。blog
驗證一下,在代碼裏造一個NPE異常時,返回結果:接口
1 { 2 "code": "01", 3 "message": "系統異常", 4 "data": null 5 }
造一個StaffPointsException異常時,返回結果:get
1 { 2 "code": "99", 3 "message": "自定義業務異常", 4 "data": null 5 }
它的做用原理,大致是先在spring初始化時將類掃描進容器,出異常後,在DispatcherServlet類的doDispatch方法中調用了對異常的攔截處理。
小結
看@RestControllerAdvice源碼能夠知道,它就是@ControllerAdvice和@ResponseBody的合併。此註解經過對異常的攔截實現的統一異常返回處理,若是你們在項目中有相似的需求,不妨試一下,好用又方便。