Spring注解之@RestControllerAdvice


前言

    前段時間部門搭建新系統,需要出異常后統一接口的返回格式,於是用到了Spring的注解@RestControllerAdvice。現在把此注解的用法總結一下。

用法

    首先定義返回對象ResponseDto

 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 }

    然后定義返回碼的枚舉類,此處只定義了兩種,有需要可以往下添加很多。

 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 }

    下面是自定義的異常類

 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行的方法,統一返回。

驗證一下,在代碼里造一個NPE異常時,返回結果:

1 {
2   "code": "01",
3   "message": "系統異常",
4   "data": null
5 }

    造一個StaffPointsException異常時,返回結果:

1 {
2   "code": "99",
3   "message": "自定義業務異常",
4   "data": null
5 }

    它的作用原理,大體是先在spring初始化時將類掃描進容器,出異常后,在DispatcherServlet類的doDispatch方法中調用了對異常的攔截處理。

小結

    看@RestControllerAdvice源碼可以知道,它就是@ControllerAdvice和@ResponseBody的合並。此注解通過對異常的攔截實現的統一異常返回處理,如果大家在項目中有類似的需求,不妨試一下,好用又方便。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM