基於 Spring Boot 的 RESTful API 設計與實現

語言: CN / TW / HK

RESTful 是一種規範,符合 RESTful 的 Api 就是 RESTful Api。簡單的說就是可聯網裝置利用 HTTP 協議通過 GET、POST、DELETE、PUT、PATCH 來操作具有 URI 標識的伺服器資源,返回統一格式的資源資訊,包括 JSON、XML、CSV、ProtoBuf、其他格式。 RESTful 的核心思想是,客戶端發出的資料操作指令都是"動詞 + 賓語"的結構。比如,GET /case 這個命令,GET 是動詞,/case 是賓語。

RESTful API簡介

  • RESTful 架構遵循統一介面原則,不論什麼樣的資源,都是通過使用相同的介面進行資源的訪問。介面應該使用標準的 HTTP 方法如 GET ,PUT 和 POST ,並遵循這些方法的語義。

設計規範

常用的動詞有以下 5 個

\ 詳情見 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 1

Spring Boot 實現 RESTful API

我們可以通過 Spring Boot 註解來實現 RESTful API 。

現在需要編寫的是對一個使用者的增刪改查操作,如下表是一個非 RESTful 和 標準 RESTful 的對比表。\

下面我們著重介紹下以下兩對註解。

Controller 一般應用在有返回介面的應用場景下。例如,管理後臺使用了模板技術如 thymeleaf 開發,需要從後臺直接返回 Model 物件到前臺,那麼這時候就需要使用 Controller 來註解。

RestController 一般應用在只有介面的應用場景下. 例如開發前後端分離的專案時,通過 Ajax 請求服務端介面,那麼介面就使用 RestController 統一註解。

需要注意的是 RestController 是 Controller 的子集。RestController 是 Spring4 後新加的註解,從 RestController 註解原始碼可以看出 RestController 是 Controller 和 ResponseBody 兩個註解的結合體,即Controller=RestController+ResponseBody。

RestController 註解原始碼

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }

RequestMapping 和GetMapping/PostMapping/PutMapping/DeleteMapping 作用一樣,其實可以相互替換,後者是前者的簡化版本。

GetMapping 其實就等於將 RequestMapping 註解的 method 屬性設定為 GET,PostMapping 其實就等於將 RequestMapping 註解的 method 屬性設定為 POST,PutMapping、DeleteMapping 其實就等於將 RequestMapping 註解的 method 屬性分別設定為 PUT、DELETE。

也就是說GetMapping、PostMapping、PutMapping、DeleteMapping 是 RequestMapping 的子集。

我們來看看 RequestMapping 的原始碼:

``` @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { String name() default "";

//請求URI
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
//請求型別,如 GET、POST、PUT、DELETE 等
RequestMethod[] method() default {};
//請求引數中必須包含某些引數值,才讓該方法處理。
String[] params() default {};
//請求引數中必須包含某些指定的header值,才能讓該方法處理請求。
String[] headers() default {};
//請求的內容型別(Content-Type),例如application/json, text/html;
String[] consumes() default {};
//響應的內容型別,僅當 request 請求頭中的( Accept )型別中包含該指定型別才返回;
String[] produces() default {};

} ```

示例說明:\ \

  • 新增 2 個檔案:dto/UserDto.java 和 controller/HogwartsTestUserController.java ,其中 UserController 類中包括了對使用者的 4 個操作增刪改查。

``` public class UserDto {

private String name;
private String pwd;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getPwd() {
    return pwd;
}

public void setPwd(String pwd) {
    this.pwd = pwd;
}

} ```

``` /* * RESTful API 風格示例 對資源 user 進行操作 * 本示例沒有使用資料庫,也沒有使用 service 類來輔助完成,所有操作在本類中完成 * / @Api(tags = "霍格沃茲測試學院-使用者管理模組", hidden = true) @RestController @RequestMapping("/api/user") public class HogwartsTestUserController {

/**
 * 查詢使用者列表,返回一個JSON陣列
 * */
@ApiOperation("查詢使用者列表")
@GetMapping("/users")
@ResponseStatus(HttpStatus.OK)
public Object getUsers(){
    List<UserDto> list = getData();
    return list;
}

/**
 * 查詢使用者資訊,返回一個新建的JSON物件
 * */
@ApiOperation("查詢使用者資訊")
@GetMapping("/users/{id}")
@ResponseStatus(HttpStatus.OK)
public Object getUser(@PathVariable("id") Long id){

    if(Objects.isNull(id)){
        return null;
    }

    List<UserDto> list= getData();
    UserDto userDto = getUserDto(id, list);

    return userDto;
}

/**
 * 新增使用者
 * */
@ApiOperation("新增使用者")
@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED)
public Object addUser(@RequestBody UserDto user){

    List<UserDto> list= getData();
    list.add(user);//模擬向列表中增加資料
    return user;
}

/**
 * 編輯使用者
 * */
@ApiOperation("編輯使用者")
@PutMapping("/users/{id}")
@ResponseStatus(HttpStatus.CREATED)
public Object editUser(@PathVariable("id") Long id,@RequestBody UserDto user){
    List<UserDto> list = getData();
    for (UserDto userDto:list) {
        if(id.equals(userDto.getId())){
            userDto = user;
            break;
        }
    }

    return user;
}

/**
 * 刪除使用者
 * */
@ApiOperation("刪除使用者")
@DeleteMapping("/users/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public Object deleteUser(@PathVariable("id") Long id){
    List<UserDto> list = getData();
    UserDto userDto = getUserDto(id, list);
    return  userDto;
}

/**
 * 模擬資料
 * */
private List<UserDto> getData(){
    List<UserDto> list=new ArrayList<>();

    UserDto userDto = new UserDto();
    userDto.setId(1L);
    userDto.setName("admin");
    userDto.setPwd("admin");
    list.add(userDto);

    userDto = new UserDto();
    userDto.setId(2L);
    userDto.setName("HogwartsTest1");
    userDto.setPwd("HogwartsTest1");
    list.add(userDto);

    userDto = new UserDto();
    userDto.setId(3L);
    userDto.setName("HogwartsTest2");
    userDto.setPwd("HogwartsTest2");
    list.add(userDto);

    userDto = new UserDto();
    userDto.setId(4L);
    userDto.setName("HogwartsTest3");
    userDto.setPwd("HogwartsTest3");
    list.add(userDto);

    return  list;
}

/**
 *  模擬根據id查詢列表中的資料
 * @param id
 * @param list
 * @return
 */
private UserDto getUserDto( Long id, List<UserDto> list) {
    UserDto UserDto = null;
    for (UserDto user : list) {
        if (id.equals(user.getId())) {
            UserDto = user;
            break;
        }
    }
    return UserDto;
}

} ```

獲取全部資源 獲取所有使用者

GET http://127.0.0.1:8081/api/user/users/

響應引數

[ { "id": 1, "name": "admin", "pwd": "admin" }, { "id": 2, "name": "HogwartsTest1", "pwd": "HogwartsTest1" }, { "id": 3, "name": "HogwartsTest2", "pwd": "HogwartsTest2" }, { "id": 4, "name": "HogwartsTest3", "pwd": "HogwartsTest3" } ]

獲取單個資源 獲取使用者

GET http://127.0.0.1:8081/api/user/users/3

新增一個資源 新增一個使用者

POST http://127.0.0.1:8081/api/user/users

請求引數

{ "id": 4, "name": "HogwartsTest5", "pwd": "HogwartsTest5" }

編輯更新一個資源

PUT http://127.0.0.1:8081/api/user/users/3

請求引數

{ "name": "HogwartsTest6", "pwd": "HogwartsTest6" }

刪除一個資源

DELETE http://127.0.0.1:8081/api/user/users/3

下面介紹一些 Spring Boot 常用配置項,通過這些常用配置項,我們可以修改 Spring Boot 的一些預設配置。\ 修改服務預設埠:

server: port: 8093

指定服務名稱:

spring: application: name: aitest

多環境配置

spring: profiles: active: dev

如上圖新建 application-dev.yml、application-test.yml、application-uat.yml、application-prod.yml 四套配置檔案環境,我們在四套配置檔案中將設定服務埠號分別設定為 8091/8092/8093/8094。

然後啟動服務,可以看到服務的埠號會和 application.yml 中啟用的環境配置資訊一致。

更多技術文章

喜歡軟體測試的小夥伴們,如果我的部落格對你有幫助、如果你喜歡我的部落格內容,請 “點贊” “評論” “收藏” 一鍵三連哦