在以SpringBoot開發Restful接口時,統一傳回友善前端進行開發和封裝,以及出現時給出響應編碼和資訊。@pdai
RESTful API接口?
- 什麼是 REST?
Representational State Transfer,翻譯是“表現層狀态轉化”。可以總結為一句話:REST 是所有 Web 應用都應該遵守的架構設計指導原則。
面向資源是 REST 最明顯的特征,對于同一個資源的一組不同的操作。資源是伺服器上一個可命名的抽象概念,資源是以名詞為核心來組織的,首先關注的是名詞。REST 要求,必須通過統一的接口來對資源執行各種操作。對于每個資源隻能執行一組有限的操作。
- 什麼是 RESTful API?
符合 REST 設計标準的 API,即 RESTful API。REST 架構設計,遵循的各項标準和準則,就是 HTTP 協定的表現,換句話說,HTTP 協定就是屬于 REST 架構的設計模式。比如,無狀态,請求-響應。
Restful相關文檔可以參考 https://restfulapi.net/
為什麼要統一封裝接口
現在大多數項目采用前後分離的模式進行開發,統一傳回友善前端進行開發和封裝,以及出現時給出響應編碼和資訊。
以查詢某個使用者接口而言,如果沒有封裝, 傳回結果如下
{
"userId": 1,
"userName": "趙一"
}
如果封裝了,傳回正常的結果如下:
{
"timestamp": 11111111111,
"status": 200,
"message": "success",
"data": {
"userId": 1,
"userName": "趙一"
}
}
異常傳回結果如下:
{
"timestamp": 11111111111,
"status": 10001,
"message": "User not exist",
"data": null
}
實作案例
如何實作上面的封裝呢?
狀态碼封裝
這裡以常見的狀态碼為例,包含responseCode 和 description兩個屬性。
如果還有其它業務狀态碼,也可以放到這個類中。
/**
* @author pdai
*/
@Getter
@AllArgsConstructor
public enum ResponseStatus {
SUCCESS("200", "success"),
FAIL("500", "failed"),
HTTP_STATUS_200("200", "ok"),
HTTP_STATUS_400("400", "request error"),
HTTP_STATUS_401("401", "no authentication"),
HTTP_STATUS_403("403", "no authorities"),
HTTP_STATUS_500("500", "server error");
public static final List<ResponseStatus> HTTP_STATUS_ALL = Collections.unmodifiableList(
Arrays.asList(HTTP_STATUS_200, HTTP_STATUS_400, HTTP_STATUS_401, HTTP_STATUS_403, HTTP_STATUS_500
));
/**
* response code
*/
private final String responseCode;
/**
* description.
*/
private final String description;
}
傳回内容封裝
包含公共的接口傳回時間,狀态status, 消息message, 以及資料data。
考慮到資料的序列化(比如在網絡上傳輸),這裡data有時候還會extends Serializable。
@Data
@Builder
public class ResponseResult<T> {
/**
* response timestamp.
*/
private long timestamp;
/**
* response code, 200 -> OK.
*/
private String status;
/**
* response message.
*/
private String message;
/**
* response data.
*/
private T data;
/**
* response success result wrapper.
*
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> success(){
return success(null);
}
/**
* response success result wrapper.
*
* @param data response data
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> success(T data){
return ResponseResult.<T>builder().data(data)
.message(ResponseStatus.SUCCESS.getDescription())
.status(ResponseStatus.SUCCESS.getResponseCode())
.timestamp(System.currentTimeMillis())
.build();
}
/**
* response error result wrapper.
*
* @param message error message
* @param <T> type of data class
* @return response result
*/
public static <T extends Serializable> ResponseResult<T> fail(String message){
return fail(null, message);
}
/**
* response error result wrapper.
*
* @param data response data
* @param message error message
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> fail(T data, String message){
return ResponseResult.<T>builder().data(data)
.message(message)
.status(ResponseStatus.FAIL.getResponseCode())
.timestamp(System.currentTimeMillis())
.build();
}
}
接口傳回時調用
/**
* @author pdai
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
/**
* @param user user param
* @return user
*/
@ApiOperation("Add/Edit User")
@PostMapping("add")
public ResponseResult<User> add(User user){
if (user.getId()==null || !userService.exists(user.getId())) {
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
} else {
user.setUpdateTime(LocalDateTime.now());
userService.update(user);
}
return ResponseResult.success(userService.find(user.getId()));
}
/**
* @return user list
*/
@ApiOperation("Query User One")
@GetMapping("edit/{userId}")
public ResponseResult<User> edit(@PathVariable("userId"){
return ResponseResult.success(userService.find(userId));
}
}