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());
}
}