文檔目錄
- 前言
- 設計階段
- 文檔
- Restful api
- 技術選型
- 開發階段
- 本地開發與聯調
- 路徑、接口狀態、登錄超時、服務器報錯
- 統一處理返回結果 登錄超時、字符串錯誤、其他字符串
- 部署測試階段
- 項目根目錄
- 自動部署
- 待解決問題
- 路由問題
- 狀態共享
- 接口測試
前言
近兩年嘗試了一些前后端分離的項目,開發流程和效率上并不是順風順水,效率與質量沒有特別顯著的提升,不過大部分是一些舊項目的維護和二期開發,架構上很難按照單頁面應用的開發模式實現,期間也遇到很多問題,最近在舊的項目上用jquery做了一個小模塊的前后端分離,并做了一下記錄和總結。愛掏網 - it200.com希望多學習多提升,如果有好的實現方法大家能多多指點。愛掏網 - it200.com
設計階段
1. 文檔
在之前的開發與本次的開發,總會遇到的一個問題就是文檔,前端用的是淘寶開源的RAP可視化接口管理工具, 搭建在我們自己的服務器上,前端定義接口是按照頁面來劃分,一個頁面對應的有幾個接口全部列在頁面名稱下,
但是經過幾個項目的實踐下來,發現java團隊的分工與前端不同,是按照功能實現來分的,前端開發一個購買的流程,會分幾個頁面,第一步,第二步,第三步,再根據每個頁面功能調用接口,編表單、校驗等業務邏輯開發,而后端是按照功能劃分,比如前端的第一步、第二步、第三步這個三個頁面都有獲取對應A\B\C列表的接口,開發上僅僅是從庫里查一下這個字段再返回給你,那么類似的功能,就會分給一個java工程師來做,對于后端效率高,接口實現上不會太分散。愛掏網 - it200.com
所以導致接口文檔有兩份,后端用Excel維護一份,前端用RAP維護一份,前端開發開始前要根據后端提供的接口文檔按照頁面劃分接口定義mock數據。愛掏網 - it200.com開發期間偶爾接口一個字段的變更就需要維護兩份,很不方便,效率反而下來了。愛掏網 - it200.com
2. Restful api
定義接口要考慮到多種情況,同時要做好規則約束,我們遇到的僅僅幾個,簡單列一下。愛掏網 - it200.com
狀態碼: 接口報錯有很多種情況,數據格式、服務器出錯等,要設計好對應提示的信息和狀態碼。愛掏網 - it200.com
提交數據類型 ajax提交數據時一般都為json,屬性不能是數組,我們內部約定,文檔可寫數組,提交時統一將數組轉為字符串。愛掏網 - it200.com
屬性與數組 文檔內所有返回值,標為list的即返回數組,沒有標識的即返回屬性。愛掏網 - it200.com
返回數據類型 我們沒有做的特別細,所以返回的類型都是字符串,前端需要統一處理成自己需要用的格式。愛掏網 - it200.com
所有入參增加params 見代碼
$.ajax({
url: "separationCommon/getDic.gsp",
type: "POST",
dataType: "JSON",
baseUrl: true,
async: false,
data: {
"params.dicCode": !code ? "DIC_EB_APPNTPROVINCE": code,
"params.searchType": 1
},
success: function (data) {
if(data.status == 200) {
var ARR = data.data.dicList;
window.STR = provinceSelect(ARR, code);
}
}
});
復制代碼
3. 技術選型
考慮到開發完以后要交給java團隊自己來維護,我們之前有用過vue和avalon,但是后端人員維護起來很麻煩,就直接用jquery+jquer.tmpl了。愛掏網 - it200.comjquer.tmpl學習成本幾乎可以忽略不計,另一方面因為是舊的項目,前端幾乎成型,左側是樹菜單,右側是load進來的jsp頁面,我們就直接使用jquery的load來加載HTML文件了。愛掏網 - it200.com
開發階段
1. 本地開發與聯調
mock工具有請求攔截的插件,可以直接實現返回數據,RAP官網文檔
但是后期聯調也需要轉發和攔截,而且還有登錄模擬,就沒有用,直接用express+http-proxy-middleware做的本地轉發
const express = require('express');
const timeout = require('connect-timeout');
const proxy = require('http-proxy-middleware');
const request = require("request");
const cheerio = require("cheerio");
const app = express();
// 超時時間
const TIME_OUT = 30 * 1e3;
// 設置端口
app.set('port', '8080');
// 設置超時 返回超時響應
app.use(timeout(TIME_OUT));
app.use((req, res, next) => {
if (!req.timedout) next();
});
proxyOption = {
target: 'http://ipaddress/mockjsdata/6',
// target: 'http://ipaddress:9527/eb/',
pathRewrite: {
'^/api/' : '/' // 重寫請求,api/解析為/
},
changeOrigin: true,
headers:{
'Cookie': ''
}
};
// 靜態資源路徑
app.use('/', express.static('src/page'));
request('http://192.168.180.87:9527/eb/syEdor/moniLongin.gsp', function(err,res,body){
// 獲取cookie
var str = res.headers['set-cookie'][0];
// 設置cookie
proxyOption.headers = {
'Cookie':str
};
if (!err && res.statusCode == 200) {
// 反向代理
app.use('/api/*', proxy(proxyOption));
}else{
console.log('登錄失敗')
}
});
// 監聽端口
app.listen(app.get('port'), () => {
console.log(`server running @${app.get('port')}`);
});
復制代碼
2. 路徑、接口狀態、登錄超時、服務器報錯
統一項目根路徑 添加部分ajax攔截,判斷條件為options.baseUrl;
// 項目路徑攔截
$.ajaxPrefilter(function (options) {
if(options.baseUrl) {
if(options.url.indexOf('/eb/') != -1) {
options.url = options.url;
} else {
options.url = '/eb/' + options.url;
}
options.crossDomain = false;
}
});
復制代碼
接口狀態、登錄超時、服務器報錯 因為報錯有很多種情況,正常的接口返回的狀態碼判斷,如果非200則統一提示, 登錄目前沒有用單頁token機制,部分還是會跳轉到jsp,部分接口報錯如500錯誤也會返回jsp,jsp的返回結果是html,也要增加判斷,請求頭內會攜帶session超時信息。愛掏網 - it200.com
//ajax請求結束
$(document).unbind('ajaxComplete').bind('ajaxComplete', function(e,xhr,opt){
if(opt.baseUrl){
var str = xhr.responseText;
try {
var obj = JSON.parse(str);
if(obj.status != 200) {
popUp(obj.msg);
}
} catch(e) {
// 通過XMLHttpRequest取得響應頭,sessionstatus
var sessionstatus = xhr.getResponseHeader('sessionstatus');
if(sessionstatus == "timeout"){
popUp('登錄超時,請重新登錄', function(){
window.location.reload();
});
}else if(sessionstatus == "perror"){
popUp('請求的鏈接地址可能存在非法字符', function(){
window.location.reload();
});
}else{
popUp('404,服務器出錯!')
}
}
}
});
復制代碼
部署測試階段
1. 項目根目錄
本地開發和調試與測試服務器的靜態資源鏈目錄不一致,頁面中有一些圖片和html文件的路徑,用gulp打包替換。愛掏網 - it200.com
gulp.task('prod:narrowImg', ['prod:narrowJs'], function () {
return gulp.src(Config.html.htmlProphaseLoad)
.pipe(replace(/src=\"\.\.\/images/g, "src=\"\/eb\/static\/images"))
.pipe(replace(/\/api\//g, "\/eb\/"))
.pipe(replace(/load\(\$\(\"#loadjsp\"\)/g, 'load("\/eb"+$("#loadjsp")'))
.pipe(rename({dirname: ''}))
.pipe(gulp.dest(Config.html.distProphaseLoad)); // 替換三期load圖片路徑
});
復制代碼
2. 自動部署
gulp-sftp 很好用,直接配置一個任務就可以了。愛掏網 - it200.com
gulp.task('ftp', function () {
return gulp.src('dist/一二期/三期/load/*.*')
.pipe(sftp({
host: 'ipaddress',
user: 'user01',
pass: 'password',
remotePath: '/application/apache9527/apache/htdocs/eb/load'
}));
})
復制代碼
待解決問題
- 路由問題 本來想使用jQuery Hashchange或jqueryRouter來實現的,考慮到之前的模式和開發時間,就沒有來替換。愛掏網 - it200.com
- 狀態共享 目前左右跨頁面的狀態都放在隱藏域的value和div的attr上,后期考慮引入Mbox做狀態管理
- 接口測試 前端聯調中,一大部分時間做了接口測試的工作,希望能夠找到好的接口測試工具和測試流程。愛掏網 - it200.com
才疏學淺,如有問題懇請斧正。愛掏網 - it200.com
原文發布時間:2024-6-20 原文作者: 愚坤 本文來源掘金如需轉載請緊急聯系作者