每一個完整的項目都是不是一個人的功勞,是一個團隊的心血!那麼在這個項目從無到有的過程中,一個團隊是如何凝聚呢?如何共享信息呢?會議及活動是如何開展呢?前端和後端又是如何對接的呢?
在剛剛收到項目時,我有很多問號?其中最大的一個就是接口是個什麼鬼,我相信大家也或多或少有這個想法。隨着學習的逐漸深入,它神祕的面紗似乎也在一層層的揭開,我們開始接觸到了postman等接口測試工具,但這還是不夠直觀。其實最好的理解在於實踐,再多的文字介紹也不如真實和前端小姐姐對接一下的效果好!(但文字還是要有的)
爲什麼需要分離呢?
隨着技術的不斷進步,對前端後端的要求也不斷升級。前端的展示業務、要求、質量、交互體驗越來越靈活、炫麗,響應體驗也要求越來越高,工作量越來越繁重!而後端責着重提供各種服務以及高併發、高可用、高性能、高擴展等。
由此導致了前後端分離。各自專注於自己負責的模塊。詳情參考
一、接口是什麼(附帶簡易案例)
由於目前項目採用SpringMVC架構,後臺接口就是servlet,我們事實上可以將接口理解爲servlet(不知道還有沒有其他類型的,如果還有其他請積極指正)。那麼servlet又是什麼呢?
servlet:
簡單的說servlet就是跑在web服務器中的小Java程序,是Java中的類,用來接受和相應網頁傳過來的東西,主要是http。
這裏暫時不介紹servlet的詳細用法,有需求的同學可以參考這篇https://blog.csdn.net/chachapaofan/article/details/82631841,這裏用一個簡單的案例來說明(因爲技術原因,只能jsp來演示調用接口,需要用到ajax詳細介紹,前端的調用本質上類似)如果是要用axios,請參考靳紫瀾同學博客
還是先介紹概念: XMLHttpRequest 對象的三個重要的屬性:
屬性 | 描述 |
---|---|
onreadystatechange | 存儲函數(或函數名),每當 readyState 屬性改變時,就會調用該函數。 |
readyState | 存有 XMLHttpRequest 的狀態。從 0 到 4 發生變化。 0: 請求未初始化 1: 服務器連接已建立 2: 請求已接收 3: 請求處理中 4: 請求已完成,且響應已就緒 |
status | 200: “OK” 404: 未找到頁面 |
在 onreadystatechange 事件中,我們規定當服務器響應已做好被處理的準備時所執行的任務。
方法 | 描述 |
---|---|
open(method,url,async) | 規定請求的類型、URL 以及是否異步處理請求。 method:請求的類型;GET 或 POST url:文件在服務器上的位置 async:true(異步)或 false(同步) |
send(string) | 將請求發送到服務器。 string:僅用於 POST 請求 |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script>
// 在頁面的 head 部分添加一個 <script> 標籤。該標籤中包含了這個 TestAjax() 函數
function TestAjax(){
//var 是創建變量
var xmlHttp;
// 所有現代瀏覽器均支持 XMLHttpRequest 對象(IE5 和 IE6 使用 ActiveXObject)。
// XMLHttpRequest 用於在後臺與服務器交換數據。這意味着可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。
// 如果支持,則創建 XMLHttpRequest 對象。如果不支持,則創建 ActiveXObject :
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼
xmlHttp = new XMLHttpRequest();
} else {
// IE6, IE5 瀏覽器執行代碼
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.onreadystatechange = function(){
//當 readyState 等於 4 且狀態爲 200 時,表示響應已就緒:readyState是XMLHttpRequest的一個屬性
if (xmlHttp.readyState==4 && xmlHttp.status==200) {
document.getElementById("sp").innerHTML = xmlHttp.responseText;
}
}
//這個地方在地址後設置了一個屬性name=LiGuorui,在servlet中會用到
xmlHttp.open("GET", "/servlet2/TestAjax?name=LiGuorui", true);
xmlHttp.send();
}
</script>
</head>
<body>
<%--當按鈕被點擊時,它負責調用名爲 TestAjax() 的函數--%>
<button onclick="TestAjax()">利用Ajax獲取數據</button> <br>
<span id = "sp"></span>
</body>
</html>
servlet
@WebServlet(name = "TestAjax",urlPatterns = "/servlet2/TestAjax")
public class TestAjax extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestAjax() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.println("Hello " + request.getParameter("name"));
out.flush();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
二、Tomcat的Servlet
由上圖可以看出Tomcat最頂層的容器是Server,代表整個服務器。一個Server可以包含至少一個Service,用於提供服務。
Service主要有兩大核心組件,Connector和Container。Connector主要負責對外交流,而container則是處理內部事務。一個Service可以有多個Connector,但只能有一個Container。
多個 Connector 和一個 Container 就形成了一個 Service,有了 Service 就可以對外提供服務了,再加上生存環境Server。整個 Tomcat 的生命週期由 Server 控制。
三、json
Java中並沒有內置JSON的解析,因此使用JSON需要藉助第三方類庫。
下面是幾個常用的 JSON 解析類庫:
-
Gson: 谷歌開發的 JSON 庫,功能十分全面。
-
FastJson: 阿里巴巴開發的 JSON 庫,性能十分優秀。
-
Jackson: 社區十分活躍且更新速度很快。
-
1.1:JSON對象
我們先來看以下數據:
{ "ID": 1001, "name": "張三", "age": 24 }
第一個數據就是一個Json對象,觀察它的數據形式,可以得出以下語法:
1:數據在花括號中
2:數據以"鍵:值"對的形式出現(其中鍵多以字符串形式出現,值可取字符串,數值,甚至其他json對象)
3:每兩個"鍵:值"對以逗號分隔(最後一個"鍵:值"對省略逗號)
遵守上面3點,便可以形成一個json對象。
1.2:JSON對象數組接下來我們再看第二個數據,觀察它的數據形式,可以得出以下語法:
[ {"ID": 1001, "name": "張三", "age": 24}, {"ID": 1002, "name": "李四", "age": 25}, {"ID": 1003, "name": "王五", "age": 22} ]
1:數據在方括號中(可理解爲數組)
2:方括號中每個數據以json對象形式出現
3:每兩個數據以逗號分隔(最後一個無需逗號)
遵守上面3點,便可形成一個json對象數組(及一個數組中,存儲了多個json對象)
理解了上面兩種基本的形式,我們就可以得出其他的數據形式,例如下面這個:
{ "部門名稱":"研發部", "部門成員":[ {"ID": 1001, "name": "張三", "age": 24}, {"ID": 1002, "name": "李四", "age": 25}, {"ID": 1003, "name": "王五", "age": 22}], "部門位置":"xx樓21號" }
這是上面兩個基本形式結合出來的一種變形,通過這種變形,使得數據的封裝具有很大的靈活性,能讓開發者自由的發揮想象力。
1.3:JSON字符串
Json字符串應滿足以下條件:
- 1它必須是一個字符串,支持字符串的各種操作
- 裏面的數據格式應該要滿足其中一個格式,可以是json對象,也可以是json對象數組或者是兩種基本形式的組合變形。
總結:json可以簡單的分爲基本形式:json對象,json對象數組。兩種基本格式組合變形出其他的形式,但其本質還是json對象或者json對象數組中的一種。json對象或對象數組可以轉化爲json字符串,使用於不同的場合。
Fastjson
在fastjson包中主要有3個類,JSON,JSONArray,JSONObject
三者之間的關係如下,JSONObject和JSONArray繼承JSON,JSONObject代表json對象,JSONArray代表json對象數組,JSON代表JSONObject和JSONArray的轉化。
這裏主要介紹兩種轉化方法
JSON類之toJSONString()方法,實現json對象轉化爲json字符串和javabean對象轉化爲json 字符串
JSON類之JSONArray()方法,實現json字符串轉化爲json對象數組或List<T>
public class Changing { /** 將集合轉換爲json格式的數據 */ public String toJson(List list){ String str = JSON.toJSONString(list); return str; } /** 將json格式的數據轉化爲泛型爲Notes類的集合 */ public List<Notes> JsonChange(String str){ List<Notes> notes = JSON.parseArray(str,Notes.class); return notes; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); Changing changing = new Changing(); List<Notes> notes = changing.JsonChange(sc.next()); for(int i=0;i<notes.size();i++){ System.out.println(notes.get(i).toString()); } List<Notes> notes1 = new ArrayList<Notes>(); Notes notes2 = new Notes(1,"測試","hhh","yes","moren"); notes1.add(0,notes2); System.out.println(changing.toJson(notes1)); //[{"category":"moren","content":"hhh","hasOpen":"yes","noteId":1,"title":"測試"},{"category":"moren","content":"hhh","hasOpen":"yes","noteId":1,"title":"測試"}] } }
/*輸入 [{"category":"moren","content":"hhh","hasOpen":"yes","noteId":1,"title":"測試"}, {"category":"moren","content":"hhh","hasOpen":"yes","noteId":1,"title":"測試"}]*/ /*輸出的 Notes{noteId=1, title='測試', content='hhh', hasOpen='yes', category='moren', creatTime='null', source='null'} Notes{noteId=1, title='測試', content='hhh', hasOpen='yes', category='moren', creatTime='null', source='null'} [{"category":"moren","content":"hhh","hasOpen":"yes","noteId":1,"title":"測試"}]*/
四、接口文檔:
在項目開發中,web項目的前後端是分離開發的。應用程序的開發,需要由前後端工程師共同定義接口,編寫接口文檔,之後大家都根據這個接口文檔進行開發,到項目結束前都要一直維護。不同的項目有自己文檔的規定,但大體上不會偏差太多,我就介紹自己的理解吧!
接口名稱 | 場景(接口)說明 | url | 請求信息 | 響應信息 | 錯誤碼 |
---|---|---|---|---|---|
顧名思義是給前端一個最直觀的影響,這個接口是做什麼的 | 描述這個接口的現狀,未開始、開發中、測試中。以及接口的用法,比如發送一個什麼樣的數據響應什麼樣的數據 | 前端請求地址。url地址裏不允許出現大寫字母,如果是兩個單詞拼接,用/分開 | 信息包含請求頭,請求參數,範例展示 | 信息包含響應頭,響應參數,範例展示 | 名稱 描述 原因 解決方案 |
請求頭(某些請求格式不同需要設置響應的請求頭)
名稱 | 默認值 | 描述 |
---|---|---|
Content-Type | application/json | - |
Host | - | |
… | … |
請求參數
名稱 | 類型 | 描述 | 必須 | 默認值 |
---|---|---|---|---|
參數名 | String、Number、Object、Array四大類 | 這個參數的作用是什麼,可以提供一個範例 | 是否必須有值 | 按自己需求 |
響應信息類似
五、管理平臺
傳統的管理通過聊天平臺,前後端的接口文檔是用word或其他形式來完成,這樣的接口文檔沒有實時性,做起來費時,看起來也不方便。
所以有了對接口文檔和接口測試一體化的強烈需求,自然接口管理平臺就誕生了!
我的小組目前使用NEI接口管理平臺,所以也主要介紹一下NEI接口管理平臺。
接口管理平臺(Netease Easy Interface),簡稱 NEI。
NEI 雖然叫接口管理平臺,但其實不只是管理接口,它可以管理整個產品,也具備項目腳手架的功能。
NEI可以創建項目組,在項目組中可以創建各自負責部分的分項目
最重要的是可以在線生成接口文檔
還有打印功能哦!這個平臺還附帶測試接口,測試用例,以及測試報告等一系列功能,可以說很全面了!但缺點是這個平臺上線時間不長,可能相關的教程不多,用戶也不多!
其他的接口管理工具也推薦一下!大家可以根據需要使用
- 阿里rap
- NEI
- Postman
- Thoughts
- Swagger