Restful Api寫法心得之二《引數接收篇》
前言
溫馨提示:可以訂閱我的微信公眾號,在手機裡看技術文件也很不錯哦o( ̄︶ ̄)o
本篇文章主要說下介面的資料引數到底該如何接收,我們知道一個http請求最重要的意義就是將資料在伺服器上進行傳入與傳出,本章主要講的也就是傳入。一次請求傳遞引數的方式主要有 URL路徑中、請求頭中、請求體中還有通過cookie等,下面我們分別對幾種方式進行講解。
MediaType的選擇
MediaType即是Internet Media Type,網際網路媒體型別;也叫做MIME型別,在Http協議訊息頭中,使用Content-Type來表示具體請求中的媒體型別資訊。
- 對於POST、PUT、PATCH這種HTTP方法,統一使用 application/json,將引數放在請求體中以JSON格式傳遞至伺服器
- 對於GET、DELETE的HTTP方法,使用預設型別(application/x-www-form-urlencoded)
★備註
特殊情況特殊考慮,例如進行檔案上傳時,使用 multipart/form-data型別等
路徑引數
對應spring mvc框架中@PathVariable註解
★備註
這裡有個注意的點,當路徑引數值中有帶點”.”的情況時,spring mvc框架中有對點做特殊處理,這導致在程式中只能接收到點之前的內容,例如你的請求是:GET https://api.zhuma.com/users/hehe.haha,後端在接收userId=’hehe.haha’時,只會接收到hehe字串,後面的部分(.haha)被捨棄掉了。
解決方式是:
package com.zhuma.demo.analyst.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);//可以讓URL路徑中帶小數點 '.' 後面的值不被忽略
}
}
請求頭引數
對應spring mvc框架中@RequestHeader註解
對於提供給APP(android、ios、pc) 的介面我們可能需要關注一些呼叫資訊,例如 使用者登入資訊、呼叫來源、app版本號、api的版本號、安全驗證資訊 等等,我們將這些資訊放入頭資訊(HTTP HEAD中),下面給出在引數命名的例子:
- X-Token 使用者的登入token(用於兌換使用者登入資訊)
- Api-Version api的版本號
- App-Version app版本號
- Call-Source 呼叫來源(IOS、ANDROID、PC、WECHAT、WEB)
- Authorization 安全校驗引數(後面會有文章詳細介紹該如何做安全校驗)
這時你可能會思考一下幾個問題:
- 為什麼需要收集 api版本號、app版本號、呼叫來源這些資訊呢?
這裡解釋下,主要有幾個原因:
- ①. 方便線上環境定位問題,這也是一個重要的原因(我們後面會講通過切面全域性列印非GET請求的介面呼叫日誌)。
- ②. 我們可以通過這些引數資訊處理我們的業務邏輯,而沒有必要在用到的時候我們才想起來讓呼叫者將資訊傳遞過來,導致同一功能性的引數,引數名和引數值不統一的情況發生。
- 是每個介面都要這些引數麼?
是的,建議將所有的介面都傳遞上述引數資訊。 - 怎麼做這些引數的校驗呢?
你可以寫個攔截器,統一校驗你的介面中全域性的header引數,如果還是不太會寫,可以參考這篇文章《統一引數校驗》
★備註
- Header引數大小寫不敏感,所以引數X-Token和X-TOEKN是一個引數
請求體引數
引數傳遞分為了大體兩種 URL請求查詢引數、請求體引數,對於請求體引數我們選擇以JSON格式傳遞過來,URL請求查詢引數、請求體引數這兩種方式分別對應了spring mvc框架中的 @RequestParam、@RequestBody兩個註解進行修飾。
我們下面以新增一個使用者舉例,用POST MAN截圖如下:
★舉例
開發例項
package com.zhuma.demo.user.web;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.zhuma.demo.comm.model.po.User;
import com.zhuma.demo.user.service.user.UserService;
import com.github.pagehelper.PageInfo;
/**
* 使用者管理控制器
*/
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public PageInfo<User> getUserList(@RequestParam(name="pageNum", defaultValue="1") Integer pageNum,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
@RequestParam(name="queryUser") User queryUser) {
return userService.pageList(queryUser, pageNum, pageSize);
}
@GetMapping("/{userId}")
User getUser(@PathVariable("userId") Long userId) {
return userService.getUserById(userId);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User addUser(@Valid @RequestBody User user) {
return userService.register(user);
}
@PutMapping
public User updateUser(@RequestBody User user) {
return userService.updateDbAndCache(user);
}
@DeleteMapping("/{userId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
void deleteUser(@PathVariable("userId") Long userId) {
userService.deleteUserById(userId);
}
}
上面我們擷取一個管理使用者的功能控制器,可能其中有一些你不瞭解的註解,例如@Valid、@ResponseStatus我們後面會講解,所以你可以先不必關注這些,我們主要看@GetMapping、@PostMapping、
@PutMapping、@DeleteMapping 分別處理查、修改、刪除功能,@RequestParam、@RequestBody 分別表示
查詢引數、json body體引數。
備註
- 在實際開發中我們可能會遇到跨域問題,開發環境中我們會自定義攔截器(AllowCrossDomainInterceptor)處理這種情況,可以看下我的這篇文章《企業實戰之攔截器解決跨域問題》。
結束語
下一篇文章我們主要講解下 《介面返回值篇》 O(∩_∩)O
歡迎關注我們的公眾號或加群,等你哦!