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 個
詳情見 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
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 中激活的環境配置資訊一緻。
[更多技術文章](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=toutiao×tamp=1662397200&author=Muller)