前后端交互的一种思路

作者: JerryL_ | 来源:发表于2017-01-14 15:51 被阅读0次

    写在前面:
    因为我是做后端的,所以难免会从后端的角度来思考问题。关于交互的设计其实是通过后端去控制前端

    这个怎么说呢,虽然都在强调前后端的松耦合,后端不应该涉足前端页面相关的东西。但是在小项目中,实际上都是后端占程序结构的主导地位,所以说,以后台去控制前端可以避免很多交互上的麻烦,可以从一定程度上减小交互格式的争论。

    说了这么多没用的,现在开始来看代码。

    核心类:

    /** * Created by liuruijie on 2016/9/28.
     * 前端页面控制
     */
    public class WebResult {
        private String status; //状态码
        private String msg; //提示信息
        private String redirectUrl; //重定向的url
        private boolean back; //返回
        private boolean refresh; //刷新页面
        private Map<String, Object> data; //数据
        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,但是在其中添加了一些方便的链式设置属性的方法。我可以通过这个类来控制前端的跳转、弹框、刷新、返回以及跳转等。使用方式也很简单:
    首先需要Controller的交互方法都是加了@ResponseBody的,因为需要将返回值序列化为json格式字符串。
    一个简便的方法是在Controller的类上使用@RestController代替@Controller,这样其每个方法默认都加上了@ResponseBody。

    @RestController
    @RequestMapping("student")
    public class StudentController{
        //...
    }
    
    //刷新
    return WebResult.buildResult().refresh();
    //返回上个页面
    return WebResult.buildResult().back();
    //发送数据
    return WebResult.buildResult().putData("user", user);
    //。。。
    

    当然只有WebResult类还是不够的。它的作用相当于只是提供了一个规范,一个前后端都必须遵守的规范。前端也需要对其进行实现才能达到真正的效果。
    来看前端的js代码:

    /**
     * Created by liuruijie on 2016/9/28.
     * 前端控制
     */
        //状态码
    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;
            }
            //跳转
            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");
       
    };
    

    其中状态码要对应后端的状态码,后端的状态码可以以常量的方式配置在一个单独的类中。

    /**
     * 系统基础参数定义
     */
    public class Config {
        //状态码
        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";
    }
    

    状态码的值无所谓,只需要对应就行了。
    一般的使用方式:

    //登陆
    AJAX.POST("/passport/login", {
        username:name,
        password:psw
    })
    //查询
    AJAX.GET("/student/1",null,function(data){
        var studentinfo = data.student;
        //将学生信息显示的页面相关操作
        //do sth.
    });
    //删除
    AJAX.DELETE("/student/1");
    //更新
    AJAX.PUT("/student/1", {code:"111",name:"lrj",classCode:"1301403"})
    

    可以看到,现在交互的前端部分,完全没有任何异常处理之类的代码,因为这些已经定义好了,所以现在前端只需要关心,页面怎么显示,怎么输出,不需要关心出错之后的弹框、跳转、刷新等等。
    到此,前后端交互部分的设计已经基本完成。

    相对完整的使用例子:
    登陆的前台代码:

    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");
        }
    }
    

    这样前端完全不用管返回值,还有操作是否成功之类的,因为这些已经提前规范好了。

    但是现在后台部分还有问题,因为后台部分的代码还是显得很不优雅。那么在下一节就着重设计后台代码,让后台的异常处理也变的简单,精简代码量。

    相关文章

      网友评论

        本文标题:前后端交互的一种思路

        本文链接:https://www.haomeiwen.com/subject/pwuebttx.html