我在公司的工作內容是,對於一個BS應用,負責服務器端開發工作,Java語言。與前端開發人員合作,最終提供給前端RESTFUL接口,保證頁面正常響應。
經驗之談
一個接口可以理解為一個業務邏輯,一個業務邏輯可以由1~n個SQL組成。一個優質的接口,應該是通用的接口,一旦需求變了,給過來的參數有變化,那我盡量做到接口不變,你多給我一個參數或者某個參數變化一下,我就可以給出你要的結果。
后端提供給前端的接口,要盡量少。最好我給你一個接口,你可以用這一個接口做很多事,拿很多數據。這樣對前端開發人員比較友好。后端開發人員對自己也要好一點,自己的mapper也要盡量通用,service層封裝方法,幾個service給出的方法,最好都是一個mapper或者幾個mapper的組合。
寫接口的時候,要考慮到接口的服役期,不要寫一個簡單的接口,臨時使用。
舉個例子,企業賬戶充值的頁面,除了充值的功能外,原型上還有一個簡單的充值記錄查詢功能,只是查找當前企業的充值記錄。如果你的接口里面,沒有將企業ID作為搜索條件傳入,那么恭喜你,你可以准備好修改了。因為雖然短時期內,前端可以調你這個接口取得數據,但是今后原型上增加了【充值記錄查詢】這個功能,用戶可以輸入企業ID作為搜索條件,你就要改接口了。你要改成一個復雜一些的接口,在充值頁面中使用,也在充值記錄查詢這個頁面中使用,前端人員還得修改充值頁面中調用的接口。這是典型的先甜后苦的情況。
為了前端和后端可以並行開發,后端開發人員應該先在RAP中定義接口並告知前端,前端開發人員就可以根據接口URL和參數,綁定到頁面的觸發函數中。
並行開發帶來效率的提升的,但是難點是要預先籌划好接口,並且在后來的開發過程中盡量保證不變,特別是數組之類的數據結構不要修改,否則前端遍歷處理的修改將會很麻煩。
要做到這樣,就需要一些后端接口開發的經驗,而且提前計划總是比較困難的,就像敏捷開發中的 Sprint Planning 總是比較難完成。但是堅持這么做,對自己的能力也是一種激勵和提升,因此推薦這么做。
返回類和分頁
返回給前端的數據,需要有Response類/ResponsePages類封裝,也就是要帶有返回碼,返回消息和返回體。如果要求給出分頁信息,那么ResponsePages類中,還需要有Page類,其中至少包括當前頁數,每頁顯示條數和總條數信息。分頁使用github的pagehelper工具類來完成。
返回碼
返回碼不可以使用http狀態碼,因為http狀態碼是有限的,而且提示信息很模糊,不足以定義豐富的業務錯誤,因此要定義自己的業務返回碼。同樣,也要成對定義業務返回消息,用於描述業務錯誤。業務分配的錯誤編碼表,需要由研發部門統籌給出。如果是服務之間調用的,應當透傳返回碼和返回消息。
http返回對象: { code: code, msg: msg, pageInfo: { // 分頁信息 curPage: 1, pageLimit: 10, page: 1, total: 10 } data: {data} }
服務之間通信
服務和服務之間調用,通過RPC接口,一般分為【api模塊】和【provider模塊】。服務的治理采用微服務框架。服務有服務名稱,服務組別和服務的版本號。 RPC的框架,2017年使用的是阿里的HSF框架,也就是Pandora容器。2018年10月開始,逐步轉成幟訊RPC框架這是一種封裝了Dubbo的RPC框架。目前正在進行架構改造。 微服務的架構下,服務部署在不同的服務器中,它們所對應的數據庫也是不同的。有的時候,數據需要聯查才可以組裝,這就要考慮網絡通信的代價。一般的做法,一次性從他處拿到數據,組裝成map或者mapList,然后再與本地的數據做匹配。注意map或者mapList要盡量小。
HSF框架
HSF框架,服務的提供者具有@HSFProvider注解,服務的消費者具有@HSFConsumer注解,兩者都會注冊到【EDAS Config Center】注冊中心,該注冊中心負責服務的注冊與發現,以及配置中心。每個服務都有Group,DataId和Version。如果在同一網段有兩個Group、DataId和Version都相同的服務同時啟動,那么注冊中心就會進行隨機調度。
幟訊RPC框架
幟訊RPC框架是封裝了Dubbo的RPC框架,支持服務治理的框架參數化傳入,可以是dubbo,也可以是市場上的任何一種RPC框架。目前默認是Dubbo。 具體來說,服務的提供者使用【@FlaginfoProvider】注解,服務的消費者使用【@FlaginfoConsumer】注解,服務組,服務名和版本號暫時不需要傳入。注意,如果要標記提供者,不可以同時使用【@FlaginfoProvider】和【@Service】標簽,否則會出現尋找實例化bean超過一個的錯誤。
我們來看一下RPC服務的代碼結構,分為【api】和【provider】,簡單來說,【api】中定義了暴露給其他服務的接口,【provider】中的內容是接口的實現。團隊協作開發的時候,當你提交新的接口,而接口jar包版本又不升級的時候,需要記得把接口實現的代碼一並提交。如果接口實現負責,一時間無法完成,那么可以先提交一個空的實現。如果你不這么做,那么當團隊其他成員嘗試發布RPC服務的時候,就會報【接口沒有實現】的編譯錯誤,影響發布。
開發雜談
RAP一定要好好使用。在寫接口之前,最好先定義好RAP,包括URL,入參和返回,這樣前端開發人員就可以根據RAP去寫前端頁面,而同時后端人員可以實現這個接口。后端開發過程中,注意RAP上定義好的內容盡量不要變更。
關於枚舉類,推薦使用Enum類來處理,好處是一次定義,多處使用,缺點是代碼量增加,而且前端后端轉換過程中要注意處理空值的情況。
一般,前端發起一個POST請求,傳過來的參數是JSON格式的,后端使用Spring的【@RequestBody】注解將其轉換成Java類,一般是一個VO。后端使用service處理以后,返回的是【@ResponseBody】類型的數據,這樣前端拿到后自動會解析成JSON格式的數據。 以上是最基本的數據類型和標簽使用,還有例如【@RestController】【@PostMapping】等,可以參看【Spring RESTful接口常用注解】。
持久層框架
后端和前端的交互,一般都是要從數據庫中取出數據,然后在前端頁面渲染。因此,后端寫接口,很重要的一點,就是去數據庫中取數據。幟訊使用的ORM框架是輕量級的MyBatis,DTO,mapper interface和xml文件,通過 MyBatis Generator自動生成。
下面來說說 MyBatis 的 xml文件。該文件可以接收VO,這樣就可以直接接收前端傳過來的參數。xml文件返回的一般是DTO,一般是DTO的List,注意調interface后要用一個List來組裝。xml文件的核心是SQL語句,用於從數據庫中取出數據。如果沒有把握,可以將SQL語句在Navicat中執行一遍,看看輸出的結果。
知識總結
我的認知中,簡單地把【RESTFul接口/調用方式】理解為前端可以調用的,后端也可以通過httpClient的方式向其他服務的URL發送請求,獲取數據;【RPC接口/調用方式】是服務之間的相互調用,前端無法直接使用。 前者通過Controller暴露出接口,前端訪問URL,同時帶上參數,如此來使用后端的服務;后者分api和provider,api暴露出接口,消費者引用提供者的api來調用。
創作日期:03/10/2018 21:32