? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ①
有一次面試,面試官問:“什么是REST風(fēng)格肥卡?”
自己也是剛接觸這一個(gè)概念溪掀,并沒有系統(tǒng)化的去學(xué)習(xí),就含含糊糊地回答:“前臺用GET請求步鉴,后臺也用GET接收揪胃;前臺用POST請求,后臺也用POST接收……”
還沒等我說完氛琢,就被面試官就打斷:“前臺用GET請求喊递,后臺用POST接收,能接收到嗎阳似?”
“額骚勘,不能〈樽啵”
“你們項(xiàng)目里用過嗎俏讹?”
“用過的⌒蟮酰”
“有接口文檔嗎泽疆?”
“有”
“接口是怎么命名的?”
當(dāng)時(shí)玲献,傻了眼于微,不知道該怎么描述,是動(dòng)詞名詞相結(jié)合嗎青自,駝峰式的命名法株依?支支吾吾了半天……更不知道面試官葫蘆里裝的什么藥,這樣問的目的是什么延窜,心里的幾只小兔子一直蹦呀跳呀恋腕,不敢輕易回答,忐忑逆瑞。
就這樣荠藤,在這場面試中伙单,灰不溜秋的敗下陣來。
回到家中哈肖,立刻翻書查資料吻育,終于明白了面試官為何這樣問。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ②?
請看這段代碼:?
@RestController
public class TestController {
????????? @RequestMapping("/test")
????????? public Object test(){
? ? ? ? ? ? ? ? return "test";
????????? }
}?
如果僅僅在Controller類上加上@RestController淤井,有了Rest字樣布疼,就認(rèn)為已經(jīng)實(shí)現(xiàn)了REST風(fēng)格,那也是大錯(cuò)特錯(cuò)了币狠,這只是RESTFul風(fēng)格的冰山一角喲游两。當(dāng)然,自己也曾經(jīng)這么傻傻地認(rèn)為漩绵。
先來說說這個(gè)@RestController的作用吧,?
@RestController = @Controller + @ResponseBody宝踪,沒錯(cuò)上面的代碼等同于下面的代碼:?
@Controller
public class TestController { ? ? ? ? ?
????????? @ResponseBody
????????? @RequestMapping("/test")
????????? public Object test(){
? ? ? ? ? ? ?? return "test";
????????? }
}
為什么等同呢蕴忆,一看運(yùn)行結(jié)果,二看源碼,請看@ResponseBody的源碼,源碼最有說服力:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ③
那到底什么是RESTFul風(fēng)格呢?看官方解釋巷挥,REST是英文Representational State Transfer的簡稱,可以翻譯為表現(xiàn)層狀態(tài)轉(zhuǎn)換。它是一種軟件架構(gòu)風(fēng)格,在兩千年的時(shí)候排作,這種思想提出了楞件,如今發(fā)展也快十個(gè)年頭了罪针,具體的可以自己網(wǎng)上搜还最,個(gè)人推薦阮一峰的網(wǎng)絡(luò)日志:http://www.ruanyifeng.com/blog/2011/09/restful.html
下面上代碼,進(jìn)入使用階段,下面的這四種是比較常用的,還有PATCH(UPDATE)、HEAD种蝶、OPTIONS這三種不常用盯滚,就不列舉了酗电。
/**
?* RESTFul風(fēng)格代碼示范
?* @author ME
?*
?*/
@RequestMapping("/user")
@RestController
public class UserController {
????????? /**
????????? ?* 新增(CREATE)
????????? ?* @param user
????????? ?* @return
????????? ?*/
??? @RequestMapping(value="/save",method= RequestMethod.POST)
??? public? Object save(User user) {
??? ????? System.out.println("數(shù)據(jù)庫持久層操作");
??? ????? returnuser.getUserMobile();
??? }
? ? /**
???? * 修改(UPDATE)
???? * @param userUid
???? * @param user
???? * @return
???? */
??? @RequestMapping(value="/{userUid}",method= RequestMethod.PUT)
??? public Object update(@PathVariableInteger userUid,User user) {
??? ????? System.out.println("數(shù)據(jù)庫持久層操作");
??? ????? returnuserUid;
??? }
??? /**
???? * 刪除數(shù)據(jù)(DELETE)
???? * @param userUid
???? * @return
???? */
??? @RequestMapping(value="/{userUid}",method= RequestMethod.DELETE)
??? public Object delete(@PathVariableString userUid) {
??? ????? System.out.println("數(shù)據(jù)庫持久層操作");
?????????????????? return userUid;
??? }
??? /**
???? * 查詢單條數(shù)據(jù)(VISIT)
???? * @param userUid
???? * @return
???? */
??? @RequestMapping(value="/{userUid}",method= RequestMethod.GET)
??? public Object info(@PathVariableString userUid) {
??? ????? System.out.println("數(shù)據(jù)庫查詢操作");??? ??????
??? ????? returnuserUid;
??? }
}
REST設(shè)計(jì)風(fēng)格魄藕,簡單地說就是資源定位,每一個(gè)資源對應(yīng)一個(gè)網(wǎng)址撵术,既然是資源背率,那就不應(yīng)該有非名詞存在。這也是上面面試官問接口命名規(guī)范的最終原因(看來不管自己怎么回答都是錯(cuò)嫩与,不回答也是錯(cuò))寝姿,如果接口的命名規(guī)范不按照這個(gè)來,那也稱不上遵循什么RESTFul設(shè)計(jì)規(guī)范了划滋。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ④
代碼寫好了饵筑,還要測試吧,GET可以直接在瀏覽器進(jìn)行測試处坪,POST根资、PUT、DELETE這三種方法可以使用模擬器測試同窘,在這里使用API POST工具玄帕。
本人使用的開發(fā)環(huán)境是Spring Boot 2.1.4.RELEASE版本的,對應(yīng)的Spring Cloud版本是Greenwich.SR1塞椎。
GET方法測試結(jié)果如下桨仿,這個(gè)方法也可以直接在瀏覽器上進(jìn)行測試睛低。
POST方法測試結(jié)果如下案狠,這個(gè)就得用模擬器進(jìn)行模擬了。
在做PUT測試時(shí)钱雷,后臺總是報(bào)錯(cuò)骂铁,報(bào)錯(cuò)信息如下:
API POST模擬工具這邊報(bào)500的錯(cuò)誤,如下圖:
org.apache.tomcat.util.http.fileupload.FileUploadException罩抗,不明白為何報(bào)上傳文件的錯(cuò)誤拉庵,難道還要限制上傳文件的大小不成,這里并沒有涉及任何上傳文件呀套蒂,只是文本類型,在網(wǎng)上查了一下資料,加了一個(gè)header就可以了柬采。
DELETE測試報(bào)的錯(cuò)誤和PUT一樣斑芜,在DELETE中杏头,只有請求頭续语,沒有body的厦画,還需要設(shè)置什么呢?
繼續(xù)踩坑,在header中加了一個(gè)Content-Type怖糊,并設(shè)置為application/x-www-form-urlencoded;好吧,這下OK了扰魂。
還有一個(gè)注意點(diǎn),附在URI后面的參數(shù),在接收時(shí)砰识,是必須加@PathVariable注解進(jìn)行修飾的,否則在后臺是獲取不到參數(shù)的。
RESTFul設(shè)計(jì)風(fēng)格的簡單使用,就告一個(gè)段落了,入門級的使用還是比較簡單的,只是在使用的過程中护盈,會(huì)遇到很多坑,需要一個(gè)一個(gè)踩,你get到了嗎撤师?
可是有人會(huì)說淤袜,做這個(gè)測試可以不用API POST工具积蔚,那用什么呢,請看下集繼續(xù)。
有一個(gè)疑問還沒有想明白幅狮,那就是Content-Type為何要換成application/x-www-form-urlencoded;? 難道是因?yàn)锳PI POST模擬了瀏覽器慌烧?
application/x-www-urlencoded是瀏覽器默認(rèn)的編碼格式
multipart/form-data是form表單提交
application/json是ajax請求