前后端交互的一種思路

寫在前面:
因?yàn)槲沂亲龊蠖说模噪y免會從后端的角度來思考問題。關(guān)于交互的設(shè)計其實(shí)是通過后端去控制前端

這個怎么說呢,雖然都在強(qiáng)調(diào)前后端的松耦合,后端不應(yīng)該涉足前端頁面相關(guān)的東西。但是在小項(xiàng)目中,實(shí)際上都是后端占程序結(jié)構(gòu)的主導(dǎo)地位,所以說,以后臺去控制前端可以避免很多交互上的麻煩,可以從一定程度上減小交互格式的爭論。

說了這么多沒用的,現(xiàn)在開始來看代碼。

核心類:

/** * Created by liuruijie on 2016/9/28.
 * 前端頁面控制
 */
public class WebResult {
    private String status; //狀態(tài)碼
    private String msg; //提示信息
    private String redirectUrl; //重定向的url
    private boolean back; //返回
    private boolean refresh; //刷新頁面
    private Map<String, Object> data; //數(shù)據(jù)
    public WebResult(){
        data = new HashMap<>();
        refresh = false;
        back = false;
        status = Config.SUCCESS;
    }
    public static WebResult buildResult(){
        return new WebResult();
    }
    public WebResult status(String status){
        setStatus(status);
        return this;
    }
    public WebResult msg(String msg){
        setMsg(msg);
        return this;
    }
    public WebResult redirectUrl(String redirectUrl){
        setRedirectUrl(redirectUrl);
        return this;
    }
    public WebResult back(){
        setBack(true);
        return this;
    }
    public WebResult refresh(){
        setRefresh(true);
        return this;
    }
    public WebResult putData(String name, Object val){
        data.put(name, val);
        return this;
    }

  
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public Map<String, Object> getData() {
        return data;
    }
    public void setData(Map<String, Object> data) {
        this.data = data;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public String getRedirectUrl() {
        return redirectUrl;
    }
    public void setRedirectUrl(String redirectUrl) {
        this.redirectUrl = redirectUrl;
    }
    public boolean isRefresh() {
        return refresh;
    }
    public void setRefresh(boolean refresh) {
        this.refresh = refresh;
    }
    public boolean isBack() {
        return back;
    }
    public void setBack(boolean back) {
        this.back = back;
    }
}

這其實(shí)是一個簡單的javabean,但是在其中添加了一些方便的鏈?zhǔn)皆O(shè)置屬性的方法。我可以通過這個類來控制前端的跳轉(zhuǎn)、彈框、刷新、返回以及跳轉(zhuǎn)等。使用方式也很簡單:
首先需要Controller的交互方法都是加了@ResponseBody的,因?yàn)樾枰獙⒎祷刂敌蛄谢癁閖son格式字符串。
一個簡便的方法是在Controller的類上使用@RestController代替@Controller,這樣其每個方法默認(rèn)都加上了@ResponseBody。

@RestController
@RequestMapping("student")
public class StudentController{
    //...
}
//刷新
return WebResult.buildResult().refresh();
//返回上個頁面
return WebResult.buildResult().back();
//發(fā)送數(shù)據(jù)
return WebResult.buildResult().putData("user", user);
//。。。

當(dāng)然只有WebResult類還是不夠的。它的作用相當(dāng)于只是提供了一個規(guī)范,一個前后端都必須遵守的規(guī)范。前端也需要對其進(jìn)行實(shí)現(xiàn)才能達(dá)到真正的效果。
來看前端的js代碼:

/**
 * Created by liuruijie on 2016/9/28.
 * 前端控制
 */
    //狀態(tài)碼
web_status = {
    SUCCESS : "000",
    FAIL : "001",
    NO_LOGIN : "003",
    NO_PRIVILEGE : "004"
};
function simpleSuccess(result) {
    //如果成功,則讀取后端返回的操作指令
    if (result.status == web_status.SUCCESS) {
        //刷新
        if(result['refresh']){
            window.location.reload();
            return;
        }
        //返回
        if(result['back']){
            window.location.href = document.referrer;
        }
        //跳轉(zhuǎn)
        if(result['redirectUrl']!=null){
            window.location.href = result.redirectUrl;
            return;
        }
        return result.data;
    }
    //未登錄
    if (result.status == web_status.NO_LOGIN) {
        alert("您還未登陸!");
        window.location.href = "/bpm/login";
    }else{
        //其他錯誤情況,直接彈出提示框
        if(result.msg!=null){
            alert(result.msg);
        }
    }
    return null;
}
//對jquery的ajax方法再次封裝
__ajax = function(url, data, success, type){
    success = success||function(data){};
    data = data||{};
    $.ajax({
        url:url,
        type:type,
        dataType:"json",
        data:data,
        success:function(result){
            success(simpleSuccess(result));
        }
    })
};
//再再次封裝
AJAX = {
  GET:function(url, data, success){
      __ajax(url, data, success, "get");
    },
    POST: function(url, data, success){
        __ajax(url, data, success, "post");
    },
    DELETE: function(url, data, success){
        __ajax(url, data, success, "delete");
    },
    PUT:function(url, data, success){
        __ajax(url, data, success, "put");
   
};

其中狀態(tài)碼要對應(yīng)后端的狀態(tài)碼,后端的狀態(tài)碼可以以常量的方式配置在一個單獨(dú)的類中。

/**
 * 系統(tǒng)基礎(chǔ)參數(shù)定義
 */
public class Config {
    //狀態(tài)碼
    public final static String SUCCESS = "000";
    public final static String FAIL = "001";
    public final static String NO_LOGIN = "003";
    public final static String NO_PRIVILEGE = "004";
}

狀態(tài)碼的值無所謂,只需要對應(yīng)就行了。
一般的使用方式:

//登陸
AJAX.POST("/passport/login", {
    username:name,
    password:psw
})
//查詢
AJAX.GET("/student/1",null,function(data){
    var studentinfo = data.student;
    //將學(xué)生信息顯示的頁面相關(guān)操作
    //do sth.
});
//刪除
AJAX.DELETE("/student/1");
//更新
AJAX.PUT("/student/1", {code:"111",name:"lrj",classCode:"1301403"})

可以看到,現(xiàn)在交互的前端部分,完全沒有任何異常處理之類的代碼,因?yàn)檫@些已經(jīng)定義好了,所以現(xiàn)在前端只需要關(guān)心,頁面怎么顯示,怎么輸出,不需要關(guān)心出錯之后的彈框、跳轉(zhuǎn)、刷新等等。
到此,前后端交互部分的設(shè)計已經(jīng)基本完成。

相對完整的使用例子:
登陸的前臺代碼:

AJAX.POST("/passport/login", {
    username:name,
    password:psw
})

登陸的后臺代碼:

@RequestMapping("login")
public Object doLogin(String username, String password){
    User user = passportService.doLogin(username, password);
    if(user==null){
        return WebResult.buildResult().msg("用戶名或密碼錯誤");
    }else{
        return WebResult.buildResult().redirectUrl("/student/index");
    }
}

這樣前端完全不用管返回值,還有操作是否成功之類的,因?yàn)檫@些已經(jīng)提前規(guī)范好了。

但是現(xiàn)在后臺部分還有問題,因?yàn)楹笈_部分的代碼還是顯得很不優(yōu)雅。那么在下一節(jié)就著重設(shè)計后臺代碼,讓后臺的異常處理也變的簡單,精簡代碼量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內(nèi)容