天天看點

SpringBoot接口 - 如何優雅的對接口傳回内容統一封裝?

在以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));
    }
}      

示例源碼

更多内容

繼續閱讀