1. 程式人生 > >基於MVC的RESTFul風格API實戰

基於MVC的RESTFul風格API實戰

### 基於`MVC`的`RESTful`風格的實現 #### 1.`RESTful`風格闡述 > `REST`服務是一種`ROA`(Resource-Oriented Architecture,面向資源的架構)應用。主要特點是方法資訊存在於`HTTP`協議的方法中(`GET`,`POST`,`PUT`,`DELETE`),作用域存在於`URL`中。例如,在一個獲取裝置資源列表的`GET`請求中,方法資訊是`GET`,作用域資訊是URI種包含的對裝置資源的過濾、分頁和排序等條件 > > ==良好的`REST API`不需要任何文件== ##### 1.1`REST`風格資源路徑 `REST`風格的資源路徑設計是面向資源的,==資源的名稱==應該是準確描述該資源的==名詞==。 > 資源路徑概覽:`sheme://host:port/path?queryString` > > 例:http://localhost:8080/bywlstudio/users/user?username=xiuer ##### 1.2`HTTP`方法 > `GET`用於==讀取==、==檢索==、==查詢==、==過濾==資源 > > `PSOT`用於==建立==一個資源 > > `PUT`用於==修改==、==更新==資源、==建立客戶端維護主鍵資訊的資源== > > `DELETE`用於==刪除==資源 **資源地址和`HTTP`方法結合在一起就可以實現對資源的完整定位** ##### 1.3`RESTful`風格`API`設計 *上文講述了通過HTTP方法和資源路徑對伺服器的一個資源進行定位的過程* 接下來看一個REST風格`API`的設計 | 功能 | 描述 | | -------------- | ------------------------------------------------------------ | | 新增/建立 | `POST/users`
`PUT/users{id}`[^建立客戶端維護主鍵資訊的資源] | | 刪除 | `DELETE/users/{id}` | | 修改/更新 | `PUT/users/{id}` | | 查詢全部 | `GET/users` | | 主鍵查詢 | `GET/users/{id}`
`GET/users?id=26` | | 分頁作用域查詢 | `GET/users?start=0&size=10`
`GET/users?07,2019-07,2020` | 可以看到通過這個`RESTAPI`都是通過對==同一個資源==的操作,所不同的就是通過不同的==HTTP方法==來實現對資源不同的處理。 #### 2.`MVC`對`REST`的支援 ##### 1.1主要通過註解來實現 * `@Controller`聲名一個處理請求的控制器 * `@RequestMapping`請求對映地址,它存在幾個子註解對於實現`REST`風格來說更加具有==語義性== * `@GETMapping` ==GET請求== * `@PUTMapping` ==PUT請求== * `@POSTMapping` ==POST請求== * `@DELETEMapping` ==DELETE請求== * `@ResponseBody` 將響應內容轉換為`JSON`格式 * `@RequestBody` 請求內容轉換為`JSON`格式 * `@PathVariable("id")`用於繫結一個引數 * `@RESTController` 等同於`@Controller`+`@ResponseBody`在類上寫了這個註解,標識這個類的所有方法只==返回資料==,而不進行==檢視跳轉== ##### 1.2返回`HTTP`狀態碼 **`REST`風格`API`一個最鮮明的特點通過返回對應的`HTTPStatus`來判斷客戶端的操作是否完成** ==下面是spring中關於`Http`狀態碼描述的列舉類,本文列舉了常見的狀態碼==(讀者若對此感興趣可以檢視`HttpStatus`原始碼) ~~~java public enum HttpStatus{ OK(200, "OK"),//用於伺服器有實體響應 CREATED(201, "Created"),//建立了新實體,響應該實體 NO_CONTENT(204, "No Content"),//伺服器正常響應,但無實體響應 BAD_REQUEST(400, "Bad Request"),//客戶端請求語法錯誤 NOT_FOUND(404, "Not Found"),//目標資源不存在 INTERNAL_SERVER_ERROR(500, "Internal Server Error"),//伺服器內部錯誤 NOT_IMPLEMENTED(501, "Not Implemented"),//伺服器不支援當前請求 } ~~~ Spring返回狀態碼是通過`@ResponseStatus`註解或者`ResponseEntity`類實現的。 ==`@ResponseStatus`方式== ~~~java @GetMapping(path = "/user/{id}" , produces = "application/json;charset=utf-8") @ResponseStatus(HttpStatus.OK) public User findUserById(@PathVariable("id")Integer id){ User user = userService.findUserById(id); return user ; } ~~~ ==`ResponseEntity`==方式 ~~~java @GetMapping(produces = "application/json;charset=utf-8") public ResponseEntity> findAll(){ List users = userService.findAll(); return new ResponseEntity>(users , HttpStatus.OK); } ~~~ ##### 1.3由於`MVC`預設不支援`PUT`和`DELETE`方法,所以需要手動開啟 *在`tomcat`伺服器的`web.xml`檔案中開啟一下配置* ~~~xml default
org.apache.catalina.servlets.DefaultServlet debug 0 listings false readonly true 1
~~~ 在專案的`web.xml`中配置 ~~~xml HiddenHttpMethodFilter org.springframework.web.filter.HiddenHttpMethodFilter HiddenHttpMethodFilter dispathcherServlet ~~~ #### 3.`MVC`實現`REST`程式碼實現 ##### 3.1例項環境 * `JDK1.8` * `maven3.60` * `tomcat9` ##### 3.2`API`設計 | URI | Description | Response | HTTPStatus | | --------------------- | ------------------------ | :------: | ---------- | | ==GET==/users | 獲取全部使用者 | `JSON` | 200 | | ==GET==/users/{id} | 獲取指定主鍵的使用者 | `JSON` | 200 | | ==PUT==/users/{id} | 修改指定的主鍵的使用者資訊 | `JSON` | 200/201 | | ==POST==/users | 增加一個使用者 | `JSON` | 201 | | ==DELETE==/users/{id} | 刪除一個使用者 | `void` | 204 | ##### 3.3控制層程式碼 ~~~java @RestController @RequestMapping("/users") public class UserControler { @Autowired private IUserService userService ; //REST風格實現方法 /** * 查詢所有 * @return */ @GetMapping(produces = "application/json;charset=utf-8") public ResponseEntity> findAll(){ List users = userService.findAll(); return new ResponseEntity>(users , HttpStatus.OK); } /**、 * 根據ID查詢 * @param id * @return */ @GetMapping(path = "/{id}" , produces = "application/json;charset=utf-8") @ResponseStatus(HttpStatus.OK) public User findUserById(@PathVariable("id")Integer id){ User user = userService.findUserById(id); return user ; } /** * 增加一個使用者 * 返回該使用者 */ @PostMapping(produces = "application/json;charset=utf-8") @ResponseStatus(HttpStatus.CREATED) public User addUser(@RequestBody User user){ User newUser = userService.addUser(user); return newUser ; } /** * 更新 * @param user */ @PutMapping(path = "/{id}" ,produces = "application/json;charset=utf-8") public ResponseEntity updateUser(@PathVariable("id") Integer id , @RequestBody User user){ user.setUid(id); //資源是否修改 boolean flag = userService.updateUser(user); User deUser = userService.findUserById(id); if(flag) return new ResponseEntity(deUser,HttpStatus.CREATED); return new ResponseEntity(deUser,HttpStatus.OK); } @DeleteMapping(path = "/{id}" , produces = "application/json;charset=utf-8") @ResponseStatus(HttpStatus.NO_CONTENT) public void delUser(@PathVariable("id") Integer id){ User user = userService.findUserById(id); userService.delUser(id); } } ~~~ 更多原創文章和Java學習資料清關注@公眾號Ma