VO是view object的简称,中文意思是视图对象,也就是我们在controller中返回给前端的内容。一般开发时,我们要按照前端给的文档给前端返回相应的内容,比如现有api如下:
路由:GET /sell/buyer/product/list
参数:无
返回:
{
"code": 0,
"msg": "成功",
"data": [
{
"name": "类目名1",
"type": 1,
"foods": [
{
"id": "123456",
"name": "商品名1",
"price": 4.5,
"description": "xxxxx",
"icon": "http://xxx.com",
}
]
},
{
"name": "类目名2",
"type": 2,
"foods": [
{
"id": "123457",
"name": "商品名2",
"price": 10.9,
"description": "xxxxx",
"icon": "http://xxx.com",
},
{
"id": "123457",
"name": "商品名3",
"price": 10.9,
"description": "xxxxx",
"icon": "http://xxx.com",
}
]
}
]
}
一个中括号就表示里面的是list。那么可以知道,最外层是由code、msg和类目的list组成;第二层就是由类目名name、type和商品的list组成;商品的list就包含了商品的信息。那么要如何构造这样的返回对象呢?先从最外层开始写。根据最外层的三个字段,可以写出ResultVo类:
/**
* 返回给前端的最外层对象
* Create by zhu on 2018/10/7
*/
@Data
public class ResultVo<T> {
private Integer code;//错误码
private String msg;//提示信息
private T data;//返回的内容
}
这里data定义为泛型,这样就可以通用。
现在将ResultVo对象返回给前端:
public ResultVo test(){
ResultVo resultVo = new ResultVo();
resultVo.setCode(0);
resultVo.setMsg("test");
resultVo.setData("这是内容");
return resultVo;
}
就会得到如下效果:
说明最外层是没有错的,根据api提供的信息又可以写出如下vo:
@Data
public class ProductVo {
//这里写的字段名与前端api需要的不一致没关系,加上如下注解,直接里面写api需要的字段名
@JsonProperty("name")
private String categoryName;
@JsonProperty("type")
private Integer categoryType;
@JsonProperty("foods")//这个foods是一个商品的list
private List<ProductInfoVo> productInfoVoList;
}
//这个就是最里层的商品对象
@Data
public class ProductInfoVo {
@JsonProperty("id")
private String productId;
@JsonProperty("name")
private String productName;
@JsonProperty("price")
private BigDecimal productPrice;
@JsonProperty("description")
private String productDescription;
@JsonProperty("icon")
private String productIcon;
}
注意,前端需要的name其实是类目名,如果这个vo也直接定义变量name,到时候会搞不清楚到底是商品的name还是类目的name。解决方案是:这里应该是什么就写什么,然后通过@JsonProperty(“xxx”)来指定返回给前端时的名字。
写好后再去controller中:
@GetMapping("/test")
public ResultVo test() {
ResultVo resultVo = new ResultVo();
ProductVo productVo = new ProductVo();
ProductInfoVo productInfoVo = new ProductInfoVo();
productInfoVo.setProductName("商品1");
productVo.setProductInfoVoList(Arrays.asList(productInfoVo));
productVo.setCategoryName("类目1");
resultVo.setData(Arrays.asList(productVo));
resultVo.setMsg("成功");
resultVo.setCode(0);
return resultVo;
}
把最里层的赋好值设置给中间层,中间层赋好值设置给最外层,再把最外层返回给前端,效果如下:
这样返回的格式就对了,和api一致。接下来要做的事就是从数据库查出相应的记录,然后赋给这三个对象就行了。
从上面的controller中可以发现,我们每次都要new一个最外层的ResultVo对象,然后setCode、setMsg、setData。每个方法中都new一个还是很麻烦的,所以可以封装一下:
public class ResultVoUtil {
/** 成功时使用 */
public static ResultVo success(Object object){
ResultVo resultVo = new ResultVo();
resultVo.setData(object);
resultVo.setCode(0);
resultVo.setMsg("成功");
return resultVo;
}
/** 成功时且不需要返回值时使用 */
public static ResultVo success(){
return success(null);
}
/** 请求错误时使用 */
public static ResultVo error(Integer code,String msg){
ResultVo resultVo = new ResultVo();
resultVo.setCode(code);
resultVo.setMsg(msg);
return resultVo;
}
}
那么上面的controller就可以改成:
@GetMapping("/test")
public ResultVo test() {
ProductVo productVo = new ProductVo();
ProductInfoVo productInfoVo = new ProductInfoVo();
productInfoVo.setProductName("商品1");
productVo.setProductInfoVoList(Arrays.asList(productInfoVo));
productVo.setCategoryName("类目1");
return ResultVoUtil.success(Arrays.asList(productVo));
}