基於 Spring Boot 的 RESTful API 設計與實現
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 中啟用的環境配置資訊一致。
喜歡軟體測試的小夥伴們,如果我的部落格對你有幫助、如果你喜歡我的部落格內容,請 “點贊” “評論” “收藏” 一鍵三連哦