Spring Boot統一REST API接口響應格式和異常處理

Spring Boot統一REST API接口響應格式和異常處理

前言

在REST API接口中,非常有必要統一接口響應格式。

示例:

{
  "code": 0,
  "message": "OK",
  "data": {
  }
}
  • code爲結果編碼,一般0表示成功,其它表示失敗
  • message爲結果描述或錯誤信息
  • data爲業務數據,可以爲空

定義統一的接口響應格式

定義ApiResponse類來作爲統一的接口響應對象。

@Data
@Builder
@Slf4j
public class ApiResponse<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private int code;

    private String message;

    private T data;

    public static <T> ApiResponse success(T data) {
        ApiResponse response = ApiResponse.builder().code(ReturnCode.SUCCESS.getCode()).message(ReturnCode.SUCCESS.getMessage()).data(data).build();
        log.info("Success API Response: {}", response.toString());
        return response;
    }

    public static ApiResponse success() {
        return success(null);
    }

    public static <T> ApiResponse fail(int code, String message) {
        ApiResponse response = ApiResponse.builder().code(code).message(message).build();
        log.error("Failed API Response: {}", response.toString());
        return response;
    }

    public static <T> ApiResponse fail(ReturnCode returnCode) {
        return fail(returnCode.getCode(), returnCode.getMessage());
    }

    public static <T> ApiResponse fail() {
        return fail(ReturnCode.FAILED);
    }

    public static <T> ApiResponse fail(String message) {
        return fail(ReturnCode.FAILED.getCode(), message);
    }
}

定義ReturnCode枚舉類來存儲系統的錯誤代碼和相應的錯誤信息:

@Getter
@AllArgsConstructor
public enum ReturnCode {
    SUCCESS(0, "OK"),
    FAILED(-1, "Failed");

    private final int code;
    private final String message;
}

後續增加系統錯誤代碼時,只需要將新的錯誤代碼和相應的錯誤信息添加到該枚舉類中。

接口調用成功時返回統一的接口響應格式

在REST API接口調用時,通過ApiResponse.success()方法返回統一的接口響應格式。

@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @PostMapping("/user")
    public ApiResponse addUser(@RequestBody User user) {
        userMapper.insertSelective(user);
        return ApiResponse.success();
    }

    @GetMapping("/user/{id}")
    public ApiResponse getUser(@PathVariable("id") String id) {
        return ApiResponse.success(userMapper.selectByPrimaryKey(Long.valueOf(id)));
    }
}

發生異常時返回統一的接口響應格式

一般是先自定義一個RuntimeException類,該類中包含錯誤代碼和相應的錯誤信息。

@Getter
public class ServiceException extends  RuntimeException {
    private int code;

    public ServiceException(int code, String message) {
        super(message);
        this.code = code;
    }

    public ServiceException(ReturnCode returnCode) {
        super(returnCode.getMessage());
        this.code = returnCode.getCode();
    }
}

再定義一個Controller異常處理器來捕獲Controller拋出的該RuntimeException,再通過ApiResponse.fail()方法返回統一的接口響應格式。

@Slf4j
@ControllerAdvice
public class ControllerExceptionHandler {

    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public ApiResponse handleServiceException(ServiceException e) {
        log.error(e.getMessage(), e);
        return ApiResponse.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    public AjaxResult handleBindException(BindException e)
    {
        log.error(e.getMessage(), e);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return ApiResponse.fail(message);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public AjaxResult handleException(Exception e)
    {
        log.error(e.getMessage(), e);
        return ApiResponse.fail(e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public AjaxResult handleRuntimeException(RuntimeException e)
    {
        log.error(e.getMessage(), e);
        return ApiResponse.fail(e.getMessage());
    }
}

參考文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章