前端技術大發展的背景下,談談先後端分離的發展與實踐,以及後端研發思想的轉變

先後端對接的思考及總結

說在前面的話

隨着前端NodeJs技術的火爆,如今的前端已經非之前傳統意義上的前端了,各類前端框架(Vue、React、Angular......)井噴式發展,配合NodeJs服務端渲染引擎,目前前端能完成的工做不只僅侷限於CSS,JS等方面,不少系統的業務邏輯均可以放在前端來完成,例如我司的管控html

那可能有些人會說,前端這麼火,NodeJs發展這麼迅猛,後端是否是之後都沒事情幹了,其實否則,拿Java來講,通過這麼多年發展,已經至關穩定,完善的生態圈也非最近今年發展起來的NodeJs可比,咱們經常說聞道有前後,術業有專攻,用在這裏最合適不過了,集羣分佈式高可用等等技術仍是須要後端架構師來思考的事情前端

目前前端同後端的合做方式是先後端分離,經過Nginx+Tomcat的組合部署(還可加nodejs中間件)方式能有效的進行解耦,而且先後端分離爲項目之後的架構擴展、微服務化、組件化都打下重要基礎,因此這在之後是一個發展的必然趨勢,咱們須要去適應,作出改變!!!java

早期的開發方式

早期的開發方式以下圖:node

輸入圖片說明

這也是我前面工做1-3年的開發方式,咱們沒有前端幫咱們寫JS函數功能,全部的頁面表單驗證,數據渲染,數據接口編寫都是咱們後端所有實現,看上去更像是一個全棧工程師,從需求分析、搭建整個技術架構、數據庫表設計、功能設計、編碼開發,再到最終部署上線,咱們無所不在,這可能也是目前不少小公司仍然在沿用的開發方式,不少後端同窗擔負起了項目的方方面面linux

以我目前的經驗來看,這樣的開發方式對我我的的成長是有益無害的,由於你只有在瞭解了前端的JS/CSS/HTML的狀況下,而後再談目前的先後端分離,會讓你的工做事半功倍,在寫後端接口前,你腦子裏浮現的是整個功能的交互頁面,最終呈現的是先後端合做開發好後的的終端結果,這大大縮減了先後端的溝通交流nginx

先後端分離的探索

jsonp

可能因爲我在前面三年積累了豐富的前端經驗,在上家公司主要負責開發官網、微信、後臺等相關係統的接口,前期咱們的開發方式雖然也是先後端分離的方式,但大都使用jsonp跨域接口調用的方式來達到分離效果,後端全部的接口都是可跨域調用的jsonp形式,拋開須要登陸的受權以外的接口,前端在開發的時候本地無需開啓服務便可調用服務端接口,而後渲染數據,完成頁面交互渲染效果git

jsonp的優勢web

不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制ajax

兼容性更好,在更低版本的ie瀏覽器中都能兼容,這裏區別於cors跨域類型redis

jsonp的原理其實很簡單,固然,這也涉及到前端的知識,簡單點說就是js端的function函數執行

正常的後端響應數據,例如:

{
    "code":"8200",
    "data":{
        "id":"100",
        "name":"Test"
        //more......
    }
}

jsonp須要的返回格式:

callback({
    "code":"8200",
    "data":{
        "id":"100",
        "name":"Test"
        //more......
    }
});

前端在頁面定義callback回調函數,callback函數接收後端響應回來的data-json數據,後端響應後執行callback函數達到調用前端業務邏輯的目的,渲染頁面

nginx+ajax

這種配合開發方式也是適合前端尚未引入Node等一站式開發解決方案的狀況下引入的,純粹的HTML+CSS+JS同後端對接,綁定業務接口,渲染數據

咱們在使用JSONP開發的時候,前端都是須要在頁面端寫死HOST+IP接口地址,存在很重大一個弊端就是前端須要些config文件,來配置咱們後端的接口請求地址,若是前端工程師規範意識強一點,會通用到一個配置文件裏,可是若是沒有這方面的意識的話,就會出現代碼裏硬編碼的狀況,不利於服務器遷移,代碼更新,接口變更等操做

爲規避上面碰到的問題,使用nginx的反向代理功能,將後端服務器代理下來,前端在開發的時候本地開啓nginx服務,即解決了jsonp跨域問題,同時也解決了無需寫死後端的服務ip+端口地址,利於後端在部署時整合代碼,減小沒必要要的錯誤

node

隨着NodeJs的火熱,前端已經能夠本地開啓服務寫接口的狀況下,就相似服務端開啓tomcat同樣,在這樣的狀況下,前端框架VUE、React等都在此基礎上,提供了一套完整的技術解決方案,這和上面說到的開啓nginx服務架構有點相似

這樣作的意義:真正的解放了先後端,專一各自擅長的領域

技術架構以下:

輸入圖片說明

前端node服務直接訪問後端Java Restful Api接口服務,Api接口最終訪問數據庫完成數據查詢最終返回node層,node渲染響應數據到前端

若是存在會話信息同步等問題,可使用中間件,例如redis緩存數據庫,解決前端node和後端Api信息同步問題,傳參能夠經過JWT等方式完成接口權限驗證

無論是jsonp仍是ajax+nginx這兩種方式,node做爲中間件均可以輕鬆切換處理,並且node做爲中間層,還能夠將多個後端接口組合成一整個數據集,最終以同步的方式渲染前端,這也利於作SEO優化,也是前面兩種方式沒法作到的

關於先後端分離,詳細可閱讀先後端分離的思考與實踐,該文章詳細的列述了關於先後端分離的實際經驗

談談接口

隨着先後端的分離,後端工程師不須要編寫頁面,不須要寫JS,只須要提供接口便可,但是就是僅僅這一個接口,對於不少後端開發工程師而言,在實際開發,同前端對接的過程當中,依然問題重重

不少後端同窗說我只負責寫接口,其餘我一律無論,這樣形成的後果就是

一、接口結構無序、雜亂無章

二、接口和實際業務場景不相匹配、不可用

三、頻繁的同前端溝通,簡單的事情複雜化,先後端都很惱火

四、事情沒作好

後端在編寫接口前,首先是對業務的理解,在對業務未理解透徹以前,編碼都是無心義的,做爲後端來講,須要鍛鍊本身對整個系統全局考慮的能力,接口之間並不是是毫無關聯的,咱們在寫第一個接口之間,其餘接口之間的業務邏輯也許考慮到,這在後端團隊合做開發不一樣功能的狀況下顯得尤其重要.

後端在開發接口時,我以爲主要從如下幾個方面須要注意:

接口url 定義

接口類型、參數

全局錯誤碼定義

接口json格式

接口文檔編寫

接口url定義

對於後端開發人員來講,接口前端入參,最終組合查詢數據庫資源,通過一系列相關業務場景下的計算,響應給前端json數據,每一層url的path定義須要清晰明瞭,這和後端在使用AOP定義事務管理同理,後端service須要知足必定的命名規範,這樣方便統一管理,並且有這層規範後,後續的先後端對接會輕鬆不少

爲了在許多API和長時間內提供一致的開發人員體驗,API使用的全部名稱應爲:

  • 簡單
  • 直覺
  • 一致

這包括接口,資源,集合,方法和消息的名稱。

因爲許多開發人員不是英文母語人士,所以這些命名約定的目標之一是確保大多數開發人員可以輕鬆瞭解API。 它經過鼓勵在命名方法和資源時使用簡單,一致和小的詞彙表來實現。

  • API中使用的名稱應該是正確的美國英語。例如,許可證(而不是許可證),顏色(而不是顏色)。
  • 能夠簡單地使用經常使用的簡短形式或長字的縮寫。例如,API優於應用程序編程接口。
  • 儘量使用直觀,熟悉的術語。例如,當描述刪除(和銷燬)資源時,刪除是優先於擦除。
  • 對同一律念使用相同的名稱或術語,包括跨API共享的概念。
  • 避免名稱重載。爲不一樣的概念使用不一樣的名稱。
  • 仔細考慮使用可能與經常使用編程語言中的關鍵字衝突的名稱。可使用這些名稱,但在API審查期間可能會觸發額外的審查。謹慎和謹慎地使用它們。

接口類型、參數

關於接口的請求類型,目前比較經常使用的:GETPOSTPUTDELETEPATCH

GET(SELECT):從服務器取出資源(一項或多項)。

POST(CREATE):在服務器新建一個資源。

PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)。

PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。

DELETE(DELETE):從服務器刪除資源。

後端可根據不一樣的業務場景定義不一樣的接口類型

在定義接口參數之時,目前咱們經常使用的幾種提交方式

表單提交,application/x-www-form-urlencoded 輸入圖片說明

表單提交主要針對key-value的提交形式

以下Java片斷:

@PostMapping("/queryAll")
public RestfulMessage queryAll(RuleCheckLogs ruleCheckLogs, @RequestParam(value = "current_page",defaultValue = "1")Integer current_page
            , @RequestParam(value = "page_size",defaultValue = "10")Integer page_size
            , @RequestParam(value = "tableName",required = false) String tableName){
        RestfulMessage restfulMessage=new RestfulMessage();
        try{
            assertArgumentNotEmpty(ruleCheckLogs.getProjectId(),"質檢方案id不能爲空"); restfulMessage.setData(qcRuleCheckLogsService.queryRuleLogsByPage(ruleCheckLogs,tableName,current_page,page_size));
        }catch (Exception e){
            restfulMessage=wrapperException(e);
        }
        return restfulMessage;
}

文件流提交

json提交,application/json

輸入圖片說明

json提交方式在SpringMVC或Spring Boot中主要有兩種,一種是以@RequestBody註解接收方式,另一種是以HttpEntity<String> requestEntity字節接收

Java代碼示例:

@PostMapping("/mergeModelEntitys")
public RestfulMessage mergeModelEntitys(HttpEntity<String> requestEntity){
    RestfulMessage restfulMessage=new RestfulMessage();
    try{
        JsonObject paramsJson = paramJson(requestEntity);
        assertJsonNotEmpty(paramsJson,"請求參數不能爲空");
        //more...
    }catch (Exception e){
        restfulMessage=wrapperException(e);
    }
    return restfulMessage;
}

全局錯誤碼定義

錯誤碼的定義同HTTP請求狀態碼同樣,對接者能經過系統定義的錯誤碼,快速瞭解接口返回錯誤信息,方便排查錯誤緣由

{
    "code": "8200",
    "message": "Success",
    "data": {
        "total_page": 1,
        "current_page": 1,
        "page_size": 10,
        "count": 5,
        "data": [
            {
                "id": "a29ab07f1d374c22a72e884d4e822b29",
                //......
            }//....
        ]
    }
}

接口json格式

後端響應json給前端須要注意如下幾點:

一、json格式需固定

例如以下圖形

輸入圖片說明

如上圖所示,橫向是時間,縱向是value值

咱們給出的json結構應該如此:

[
    {
        "date":"2018-01",
        "value":100
    },
    {
        "date":"2018-02",
        "value":200
    }
    //more...
]

在工做中,咱們常常遇見這樣的數據格式:

[
    "2018-01":{
    	value:100
    },
    "2018-02":{
    	value:200
    }
    //more...
]

這裏所說的json格式固定主要針對此種狀況,後端給到前端的接口格式必須是固定的,全部動態數據值都需相應的key與之對應

二、全部返回接口數據需直接可用,越簡單越好

後端提供給前端的接口數據,最終交給前端的工做,只須要讓前端渲染數據便可,越簡單越好,不因摻雜過多的業務邏輯讓前端處理,全部複雜的業務邏輯,能合併規避掉的都需後端處理掉.

接口文檔編寫

接口文檔編寫是先後端對接重要依據,後端寫明接口文檔,前端根據接口文檔對接

文檔形勢目前主要分幾種:

一、依賴swagger框架,自動生成接口文檔(swagger只能生成基於key-value詳細參數方式,針對json格式,沒法說明具體請求內容)

二、手動編寫說明文檔,推薦markdown編寫

接口對接

萬事俱備,只欠東風,雖然上面咱們準備了全部咱們該準備的,接口定義天衣無縫,接口文檔也已說明,但在對接時任然可能出現問題,此時我想咱們還需注意的細節

一、後端接口需自行進行Junit單元測試

Spring目前集成Junit框架可方便進行單元測試,包括對業務bean的方法測試,以及針對api的mock測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class QcWebApplicationTests {

	@Autowired
	private WebApplicationContext context;

	private MockMvc mvc;

	@Autowired
	QcFieldService qcFieldService;

	@Before
	public void setUp() throws Exception {
        //初始化mock對象
		mvc = MockMvcBuilders.webAppContextSetup(context).build();
	}

	@Test
	public void queryByDsId(){
		try {
            //針對mock-接口Controller層測試
			mvc.perform(MockMvcRequestBuilders.post("/qc/entity/queryByDsId")
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    .param("dsId", "7d4c101498c742368ef7232f492b95bc")
                    .accept(MediaType.APPLICATION_JSON))
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    @Test
    public void testUpdateField(){
		QcField qcField=new QcField();
		qcField.setId("513ee55f5dc2498cb69b14b558bc73e6");
		qcField.setShortName("密碼");
        //業務bean-service方法測試
		qcFieldService.updateBatchFields(Lists.newArrayList(qcField));
	}

二、使用工具測試,推薦PostMan

做爲接口調試神器,Postman大名想必你們都已知道

做爲後端來講,咱們須要學會查看chrome推薦給咱們的審查元素的功能,可參看Chrome開發工具介紹

chrome提供了一個能夠copy當前接口的url功能,最終生成curl命令行

輸入圖片說明

最終經過Copy as cURL(bash)功能可生成curl命令

curl 'http://demo.com/qc/ds/getAll' -H 'Origin: http://demo.com' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Referer: http://demo.com/index.html' -H 'Connection: keep-alive' --data 'current_page=1&page_size=6&' --compressed

以上命令能夠在Linux等各終端直接執行

curl命令是一個利用URL規則在命令行下工做的文件傳輸工具。它支持文件的上傳和下載,因此是綜合傳輸工具,但按傳統,習慣稱curl爲下載工具。做爲一款強力工具,curl支持包括HTTP、HTTPS、ftp等衆多協議,還支持POST、cookies、認證、從指定偏移處下載部分文件、用戶代理字符串、限速、文件大小、進度條等特徵。作網頁處理流程和數據檢索自動化,curl能夠祝一臂之力。

postman提供導入curl命令行

輸入圖片說明

三、先後端需心平氣和溝通,勿推卸責任,先後端開發人員水平不盡相同,做爲同事,須要的是團結合做,努力將事情作好,而非相互推卸

結語

先後端分離,簡化了咱們的開發方式,不一樣人專一於不一樣的領域,技術價值最大化,大大提升工做效率,咱們在掌握這些技能的同時,也須要增強自身的發展,以適應當前的技術發展趨勢,無論是前端仍是後端,多瞭解一些,老是沒錯的,古人云:技多不壓身,我想也正是此理!!!

最後

最後,推薦一個Swagger的Ui工具swagger-bootstrap-ui項目,Java開發者若是使用swagger的話能夠直接使用,很方便哦,先後端接口對接更加方便、清晰.快試試吧

相關文章
相關標籤/搜索