在应用开发中,为了提高开发效率通常需要对后端的响应结果定义统一的规范,即无论失败还是成功,返回的响应信息都应该具备固定的样式。
本文即介绍如何在 Spring Boot
接口开发中实现统一的响应结果规范。
1. 前提准备
在开始前先准备实体类 ResponseData
作用统一返回的结果对象。
ResponseData
中定义了 success()
与 failed()
两个方法分别对应成功请求与程序异常。
@Data
public class ResponseData {
private int code;
private String message;
private Object data;
public static ResponseData success(Object data) {
ResponseData response = new ResponseData();
response.setCode(200);
response.setMessage("success");
response.setData(data);
return response;
}
public static ResponseData failed(String message) {
ResponseData response = new ResponseData();
response.setCode(500);
response.setMessage(message);
response.setData(null);
return response;
}
}
2. 异常处理
针对程序运行中的异常我们需要单独进行处理,新建处理类 ExceptionHandle
并通过 @RestControllerAdvice
与 @ExceptionHandler
注解实现异常的捕获监听处理。
@RestControllerAdvice
public class ExceptionHandle {
/**
* 监听异常请求并处理返回
*/
@ExceptionHandler(Exception.class)
public ResponseData handleNotFoundException(Exception ex) {
return ResponseData.failed(ex.getMessage());
}
}
3. 结果封装
通过 @RestControllerAdvice
注解与 ResponseBodyAdvice
接口我们接口实现返回结果的统一封装。
ResponseBodyAdvice
接口类中存在两个接口方法:
- supports():用于控制是否启用。
- beforeBodyWrite():用于控制具体实现逻辑。
java
@RestControllerAdvice
public class ResponseHandle implements ResponseBodyAdvice<Object> {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
ResponseData responseData;
responseData = ResponseData.success(o);
if (o instanceof String) {
// String 类型需要转为 Json 格式返回
return objectMapper.writeValueAsString(responseData);
} else if (o instanceof ResponseData) {
// 异常处理中已经包了一层这里直接返回
return o;
} else {
return responseData;
}
}
}
4. 示例演示
完成上述配置之后新建如下几个测试接口:
@RestController
@RequestMapping("/api/seal")
public class BasicController {
@GetMapping("demo1")
public int demo1() {
return 1;
}
@GetMapping("demo2")
public boolean demo2() {
return true;
}
@GetMapping("demo3")
public String demo3() {
return "Hello";
}
@GetMapping("demo4")
public User demo4() {
return new User("123", "Alex", "Test user");
}
@GetMapping("demo5")
public List<User> demo5() {
List<User> userList = new ArrayList<>();
for (int i = 1; i < 3; i++) {
userList.add(new User(i + "", "user-" + i, "Test user " + i));
}
return userList;
}
@GetMapping("demo6")
public String demo6() throws DemoException {
throw new DemoException("Program went wrong!");
}
}
上述示例接口的请求效果如下: