开发接口的过程中经常会遇到传出值的屏蔽问题,往往要删掉一些信息才能传给调用者,但是频繁的调用set不仅耗时而且容易错漏。
这个时候会开始考虑用Apache BeanUtils、PropertyUtils,Spring BeanUtils,Cglib BeanCopier这些提供的工具类,但是有些项目里根本没有这些jar包,就为了用这一个功能,还得自己添加。这种情况下还不如用反射自己手写一个。
思路是新建一个对应的VO类,只写上接口需要的数据字段。为了减少遍历次数,最外层遍历VO的字段,里面遍历Model的字段,如果字段名一样表示需要拷贝,拷贝的时候根据需要转换数据类型。
/**
* model转成可显示出去的类
* @param model
* @param vo
*/
public static void modelToVo(Object model, Object vo){
Class clOne = model.getClass();
Class clTwo = vo.getClass();
Field[] fieldModel = clOne.getDeclaredFields();
Field[] fieldVo = clTwo.getDeclaredFields();
// 调用get方法
for (int i = 0; i < fieldVo.length; i++){
try{
// model获取get
Method getMethod = clOne.getDeclaredMethod("get" + captureName(fieldVo[i].getName()), new Class[]{});
Object ob = getMethod.invoke(model, new Class[]{});
if (null != ob){
Class modelFieldClass = String.class;
for (int j = 0; j < fieldModel.length; j++){
if (fieldVo[i].getName().equals(fieldModel[j].getName())){
modelFieldClass = fieldModel[j].getType();
break;
}
}
//处理日期格式
if ("Timestamp".equals(modelFieldClass.getSimpleName())){
Timestamp t = (Timestamp)ob;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ob = sdf.format(t);
}else if ("java.util.Date".equals(modelFieldClass.getName())){
java.util.Date d = (java.util.Date)ob;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ob = sdf.format(d);
}else if ("java.sql.Date".equals(modelFieldClass.getName())){
java.sql.Date d = (java.sql.Date)ob;
Timestamp t = new Timestamp(d.getTime());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ob = sdf.format(t);
}
// vo获取set
Method setMethod = clTwo.getDeclaredMethod("set" + captureName(fieldVo[i].getName()), new Class[]{String.class});
setMethod.invoke(vo, new Object[]{ob});
}
}catch (NoSuchMethodException e){
e.printStackTrace();
}catch (InvocationTargetException e){
e.printStackTrace();
}catch (IllegalAccessException e){
e.printStackTrace();
}
}
}
//将首字母大写
private static String captureName(String name) {
char[] cs=name.toCharArray();
cs[0]-=32;
return String.valueOf(cs);
}
}
最后,关于性能问题,暂无测试,但能应付一些简单的拷贝。
不频繁的调用这个方法还是能流畅的,如果频繁调用(比如10000次),就要加缓存了