现在项目都是前后端分离,项目中一般也要求前端不写逻辑,所以前端的小伙伴一般都要后端的输出能直接用,即使状态名称、性别名称之类的数据也要后端和数据一次性给前端。而对于后端来说,从数据库中取出来的数据类model(有的叫pojo或者entity或者其他)只会有状态编码,是不会有状态名称的,所以需要重新组装一个新的类,这也是VO的主要作用。
比如Student类
@Data
public class Student {
// 主键ID
private Integer id;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别 0 未知 1 男 2 女
private Integer gender;
// 状态 0 无效数据 1 有效数据
private Integer status;
}
输出的VO为 StudentVo
@Data
public class StudentVO {
// 主键ID
private Integer id;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别 0 未知 1 男 2 女
private Integer gender;
// 性别名称
private String genderName
// 状态 0 无效数据 1 有效数据
private Integer status;
// 状态名称
private String statusName;
}
或者定义为
@Data
public class StudentVO extends Student {
// 性别名称
private String genderName;
// 状态名称
private String statusName;
}
按以上例子把Student的数据赋值给StudentVo可能需要如下操作:
Student student = studentService.get(id);
StudentVO studentVo = new StudentVo();
studentVo.setId(student.getId());
studentVo.setName(student.getName());
studentVo.setAge(student.getAge());
studentVo.setGender(student.getGender());
studentVo.setStatus(student.getStatus());
studentVo.setGenderName(...);
studentVo.setStatusName(...);
显然,如果数据过多这样会比较麻烦,有一些其他办法输出或者转换,比如转换成Map格式,再put添加genderName和statusName。
如果按照第二种方式使用VO的话,因为Student和StudentVo是父子关系,可以采用以下方式转换:
public static <T> T superToObj(Object superObj, Class<T> clazz)
throws ReflectiveOperationException {
Class<?> clsOrig = superObj.getClass();
T t = clazz.newInstance();
for (Field field : clsOrig.getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(superObj);
field.set(t, value);
}
return t;
}
以上方法要求两个类必须是父子关系,并且不支持子类对父类的赋值
StudentVo studentVo = superToObject(student, StudentVo.class);
如果是子类对父类的赋值,可以用类型转换:
Student student = (Student)stduentVo;
附:Object转Map的方法:
/**
* Object类型数据转成Map结构
* @param object 任意类的对象
* @return map结构数据
* @throws IllegalAccessException
*/
public static Map<String, Object> objectToMap(Object object)
throws IllegalAccessException {
Map<String, Object> map = new HashMap<>();
Class<?> cla = object.getClass();
Field[] fields = cla.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String keyName = field.getName();
Object value = field.get(object);
map.put(keyName, value);
}
return map;
}
当然,如果允许的话,比较省事的方法是直接把model定义成Vo形式的数据,从数据库中取到值之后,直接set说明字段就行了。