前后端交互的一種思路

寫在前面:
因為我是做后端的,所以難免會從后端的角度來思考問題。關(guān)于交互的設(shè)計其實是通過后端去控制前端。

這個怎么說呢,雖然都在強調(diào)前后端的松耦合,后端不應(yīng)該涉足前端頁面相關(guān)的東西。但是在小項目中,實際上都是后端占程序結(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;
    }
}

這其實是一個簡單的javabean,但是在其中添加了一些方便的鏈?zhǔn)皆O(shè)置屬性的方法。我可以通過這個類來控制前端的跳轉(zhuǎn)、彈框、刷新、返回以及跳轉(zhuǎn)等。使用方式也很簡單:
首先需要Controller的交互方法都是加了@ResponseBody的,因為需要將返回值序列化為json格式字符串。
一個簡便的方法是在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ī)范。前端也需要對其進行實現(xiàn)才能達到真正的效果。
來看前端的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)碼可以以常量的方式配置在一個單獨的類中。

/**
 * 系統(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)在交互的前端部分,完全沒有任何異常處理之類的代碼,因為這些已經(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");
    }
}

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容