写在前面:
因为我是做后端的,所以难免会从后端的角度来思考问题。关于交互的设计其实是通过后端去控制前端。
这个怎么说呢,虽然都在强调前后端的松耦合,后端不应该涉足前端页面相关的东西。但是在小项目中,实际上都是后端占程序结构的主导地位,所以说,以后台去控制前端可以避免很多交互上的麻烦,可以从一定程度上减小交互格式的争论。
说了这么多没用的,现在开始来看代码。
核心类:
/** * 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");
}
}
这样前端完全不用管返回值,还有操作是否成功之类的,因为这些已经提前规范好了。
但是现在后台部分还有问题,因为后台部分的代码还是显得很不优雅。那么在下一节就着重设计后台代码,让后台的异常处理也变的简单,精简代码量。
网友评论