说明:这玩意不比BeanUtils快,而且
所花费的时间要超过取数 据、将其复制到对应的 value对象(通过手动调用get和set方法),以及通过串行化将其返回到远程的客户机的时间总和。但是也很快了,具体请根据你的业务需求使用
一个常见场景
web前端框架接收一个post请求,参数比较多,我们单独创建一个Vo用于接收
接收之后,需要将这些参数直接或者逻辑处理后设置进与数据库映射的实体类,再保存入数据库
那些不需要处理的参数,可以直接复制过来,不需要一个一个get和set处理,节约代码和时间
上工具类代码
PropertyUtility.java
其中有注释和源码,可以仔细阅读和尝试使用,验证其功效
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import dev.fpxgroup.common.utility.DateParser;
import dev.fpxgroup.common.utility.DateUtility;
import dev.fpxgroup.common.utility.StringUtility;
/**
* 对象属性的公共方法
*
* Author: lijinquan
* Created Time: 2017-06-03
*/
public final class PropertyUtility {
private final static String SET = "set";
private final static String GET = "get";
public final static String ENTER = "\r\n";
private final static String SPACE = " ";
private final static String COLON = ":";
private final static String TABS = "\t";
private final static String DOTZERO = ".0";
/**
* 得到对象的ToString的内容
*
* @param obj Object
* @param entered boolean
* @return String
*/
public static String getPropertyToString(Object obj, boolean entered) {
if (obj == null)
return "";
if (isBroadPrimitive(obj.getClass()))
return String.valueOf(obj);
StringBuilder desc = new StringBuilder();
desc.append(obj.getClass().getName()).append(TABS);
try {
Field[] aobjField = getDeclaredFields(obj.getClass());
for (Field field : aobjField) {
try {
desc.append(SPACE + field.getName() + COLON);
Object objValue = getProperty(obj, field.getName());
desc.append(objValue);
if (entered)
desc.append(ENTER);
} catch (Exception e) {
//Do Nothing
}
}
} catch (Exception e) {
//Do Nothing
}
return desc.toString();
}
public static String getPropertyToString(Object obj) {
return getPropertyToString(obj, false);
}
public static String getListToString(List list) {
StringBuffer buffer = new StringBuffer();
if(list != null && list.size() > 0 ){
for(Object ob : list ){
buffer.append(getPropertyToString(ob, true)+ENTER);;
}
}
return buffer.toString();
}
/**
* 是广义原子类型,即是字符串、原始类型或Box原始类型
*
* @param clzSource
* @return
*/
public static boolean isBroadPrimitive(Class clzSource) {
if (clzSource == String.class || clzSource.isPrimitive() || isPrimitive(clzSource))
return true;
else
return false;
}
/**
* <p>@description 判断是否为Map</p>
* Author: lijinquan
* Created Time: 2017-06-03
* @lastModificationDate 2013-8-15
* @remark
* @param clazz
* @return
*/
public static boolean isMap(Class<?> clazz) {
if (HashMap.class == clazz || LinkedHashMap.class == clazz) {
return true;
}
return false;
}
/**
* 判断是否为原始数据类型
*
* @param clzType Class
* @return boolean
*/
public static boolean isPrimitive(Class clzType) {
if (clzType == Integer.class || clzType == Boolean.class || clzType == Float.class || clzType == Double.class
|| clzType == Short.class || clzType == Long.class || clzType == short.class || clzType == long.class
|| clzType == int.class || clzType == boolean.class || clzType == float.class || clzType == double.class) {
return true;
} else {
return false;
}
}
public static boolean isPrimitive(Object target, String property) {
Class classX = getDeclaredFieldClass(target.getClass(), property);
return isPrimitive(classX);
}
/**
* 得到本类及其父类的所有属性
* Author: lijinquan
* Created Time: 2017-06-03
* @param clzParse Class
* @return Field[]
*/
public static Field[] getDeclaredFields(Class clzParse) {
Field[] aobjField = clzParse.getDeclaredFields();
Field[] aobjFieldResult = aobjField;
Class superClz = clzParse.getSuperclass();
//用While循环替换递归调用
//这里存在一个BUG,当父类有的属性子类也存在时,应该只保留子类的Field
while (superClz != null) {
Field[] aobjSuperField = superClz.getDeclaredFields();
if (aobjSuperField != null && aobjSuperField.length > 0) {
int srcLength = aobjFieldResult.length;
aobjField = new Field[srcLength + aobjSuperField.length];
System.arraycopy(aobjFieldResult, 0, aobjField, 0, srcLength);
System.arraycopy(aobjSuperField, 0, aobjField, srcLength, aobjSuperField.length);
aobjFieldResult = aobjField;
}
superClz = superClz.getSuperclass();
}
return aobjFieldResult;
}
/**
* 得到本类和父类的字段的Class
* Author: lijinquan
* Created Time: 2017-06-03
* @param clzParse Class
* @param property String
* @return Class
*/
public static Class getDeclaredFieldClass(Class clzParse, String property) {
Field[] arrField = getDeclaredFields(clzParse);
for (Field field : arrField) {
if (field.getName().equals(property))
return field.getType();
}
return null;
}
public static void setPropertyIgnoreCase(Object dest, String property, Object value) throws Exception {
Field[] arrField = getDeclaredFields(dest.getClass());
for (Field elem : arrField) {
if (elem.getName().equalsIgnoreCase(property)) {
setProperty(dest, elem.getName(), value);
break;
}
}
}
/**
* 设置属性
*
* @param dest Object
* @param property String
* @param value Object
* @throws Exception
*/
public static void setProperty(Object dest, String property, Object value) throws Exception {
if (dest == null || value == null || StringUtility.isNull(property))
return;
Class argumentType = getDeclaredFieldClass(dest.getClass(), property);
Class[] aobjClass = {argumentType};
String strFunction = SET + property.substring(0, 1).toUpperCase() + property.substring(1);
Method objMethod = dest.getClass().getMethod(strFunction, aobjClass);
objMethod.setAccessible(true);
Object tranferValue = value;
if (argumentType == Integer.class || argumentType == int.class) {
tranferValue = Integer.parseInt(trimDotForInteger(value.toString()));
} else if (argumentType == Float.class || argumentType == float.class) {
tranferValue = Float.parseFloat(value.toString());
} else if (argumentType == Boolean.class || argumentType == boolean.class) {
tranferValue = Boolean.parseBoolean(value.toString());
} else if (argumentType == Double.class || argumentType == double.class) {
tranferValue = Double.parseDouble(value.toString());
} else if (argumentType == Short.class || argumentType == short.class) {
tranferValue = Short.parseShort(value.toString());
} else if (argumentType == Long.class || argumentType == long.class ) {
tranferValue = Long.parseLong(trimDotForInteger(value.toString()));
} else if (argumentType == String.class) {
tranferValue = value.toString();
} else if (argumentType == String.class && value.getClass() == Date.class) {
tranferValue = DateUtility.getDatetime((Date) value);
} else if (argumentType == Date.class && value.getClass() == String.class) {
tranferValue = new DateParser().parse((String) value);
} else if (argumentType == BigDecimal.class) {
tranferValue = BigDecimal.valueOf(Double.parseDouble(value.toString()));
}
// 构造执行参数
Object[] aobjPD = {tranferValue};
objMethod.invoke(dest, aobjPD);
}
/**
* sValue为整形数据,后面有加了 .0, 需要将这个 .0去掉
*
* @param sValue String
* @return String
*/
private static String trimDotForInteger(String sValue) {
if (sValue.endsWith(DOTZERO))
sValue = sValue.substring(0, sValue.length() - DOTZERO.length());
return sValue;
}
/**
* 得到属性的值
*
* @param target Object
* @param property String
* @return Object
* @throws Exception
*/
public static Object getProperty(Object target, String property)
throws Exception {
if (target == null || property == null)
return null;
String strFunction = GET + property.substring(0, 1).toUpperCase()
+ property.substring(1);
Method objMethod = null;
try {
objMethod = target.getClass().getMethod(strFunction);
objMethod.setAccessible(true);
return objMethod.invoke(target);
} catch (NoSuchMethodException e) {
// e.printStackTrace();
} catch (SecurityException e) {
}
return null;
}
/**
* 将原对象里面的值copy到目标对象中,只是String -> 基本类型 和基本类型 ->String的转换
* 原对象中存在空值也会copy
*
* @param desc Object
* @param src Object
* @throws Exception
*/
public static void copyProperty(Object dest, Object src) throws Exception {
_copyProperty(dest, src, true);
}
/**
* 原对象中如果是空值就不会Copy
*
* @param dest Object
* @param src Object
* @throws Exception
*/
public static void copyProperty2(Object dest, Object src) throws Exception {
_copyProperty(dest, src, false);
}
/**
* 将原对象中不为空的属性, copy到目标对象中。 如果目标对象中的该属性不为空就不copy.
*
* @param dest Object
* @param src Object
* @throws Exception
*/
public static void copyProperty3(Object dest, Object src) throws Exception {
Field[] destFields = getDeclaredFields(dest.getClass());
Field[] srcFields = getDeclaredFields(src.getClass());
for (Field field : destFields) {
try {
if (isExisted(field, srcFields)) {
Object objsrcValue = getProperty(src, field.getName());
Object objdestValue = getProperty(dest, field.getName());
if (objsrcValue != null && objdestValue == null)
setProperty(dest, field.getName(), objsrcValue);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
private static void _copyProperty(Object dest, Object src, boolean nullCopyed) throws Exception {
Field[] destFields = getDeclaredFields(dest.getClass()), srcFields = getDeclaredFields(src.getClass());
Object objValue = null;
for (Field field : destFields) {
try {
if (isExisted(field, srcFields)) {
objValue = getProperty(src, field.getName());
if (objValue != null || (objValue == null && nullCopyed))
setProperty(dest, field.getName(), objValue);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
/**
* 判断字段是否存在于字段数组中
*
* @param field Field
* @param allFields Field[]
* @return boolean
*/
private static boolean isExisted(Field field, Field[] allFields) {
for (int i = 0; i < allFields.length; i++) {
if (field.getName().equals(allFields[i].getName()))
return true;
}
return false;
}
/**
* 判断对象中是否存在指定的属性
*
* @param target Object
* @param sProperty String
* @return boolean
*/
public static boolean isExisted(Object target, String sProperty) {
return isExisted(target.getClass(), sProperty);
}
public static boolean isExisted(Class target, String sProperty) {
Field[] destFields = getDeclaredFields(target);
boolean result = false;
for (int i = 0; i < destFields.length; i++) {
if (destFields[i].getName().equals(sProperty)) {
result = true;
break;
}
}
return result;
}
/**
* 创建对象, 并将原对象里面的内容COPY到新对象中
*
* @param dest Class
* @param src Object
* @return Object
* @throws Exception
*/
public static Object createObject(Class dest, Object src) throws Exception {
Object destObject = dest.newInstance();
copyProperty(destObject, src);
return destObject;
}
/**
* 复制原始对象属性到目标对象中
* @param dest
* @param src
* @param nullCopy 原始对象属性为空是否复制
* @param emptyFlag 如果#overrideForce 为true,此字段生效。若原始对象有emptyFlag值的字段,则将目标对象中该字段置为空
* @throws Exception
*/
public static void copyProperty4(Object dest, Object src,
boolean nullCopy, String emptyFlag)
throws Exception {
Field[] destFields = getDeclaredFields(dest.getClass());
Field[] srcFields = getDeclaredFields(src.getClass());
Object objSrcValue = null;
Object objdestValue = null;
for (Field field : destFields) {
if (isExisted(field, srcFields)) {
objSrcValue = getProperty(src, field.getName());
objdestValue = getProperty(dest, field.getName());
if (nullCopy) {
if (!StringUtility.isNull(emptyFlag)
&& emptyFlag.equals(objSrcValue)) {
objSrcValue = "";
}
setProperty(dest, field.getName(), objSrcValue);
}else {
if (!isEmpty(objSrcValue) ) {
if (!StringUtility.isNull(emptyFlag)
&& emptyFlag.equals(objSrcValue)) {
objSrcValue = "";
}
setProperty(dest, field.getName(), objSrcValue);
}
}
}
}
}
private static boolean isEmpty(Object obj) {
if (obj==null) {
return true;
}
if (obj instanceof String) {
return obj == null||"".equals(obj.toString());
}else if (obj instanceof Integer||obj instanceof Double||obj instanceof Long) {
return obj==null||Double.parseDouble(obj.toString())==0;
}
return false;
}
}
使用案例1:
准备两个实体类TuserVo.java
public class TUserVo extends Parameter implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
//用户编号
private Integer urId;
//年龄
private Integer age;
//姓名
private String uaName;
//生日
private String birthday;
@TODO get和set方法省略
}
和数据库映射的实体类
public class TUser extends Parameter implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
//用户编号
private Integer urId;
//年龄
private Integer age;
//姓名
private String uaName;
//生日
private String birthday;
//生肖
private String zodiac;
@TODO get和set方法省略
}
两个具备大多数相同属性的类型,可以复制
比如,我们接收参数的vo,复制进实体类,缺失或者需要逻辑处理的值,可以取出处理后单独set
/**
* 用户添加/编辑
*
* @return
* @throws Exception
* @return ResultVO<TUserAddress>
*/
@POST
@Path("/addUser")
@Produces({ "application/json" })
public ResultVO<TUserVo> addUserAddress(@FormParam("") TUserVo parameter) throws Exception{
@TODO 业务逻辑
}
假设TUserVo的很多属性和user一样,那先执行如下
TUser user=new TUser();
PropertyUtility.copyProperty3(user, userVo);
这样操作后,userVo和user相同属性复制到了user中
因为userVo作为前端接受参数的类型,属性更加多样和灵活,假如user实体类其中有一个属性用户生肖(zodiac),需要拿userVo传进来的生日进行运算
那完全可以在使用工具类复制后,单独再设置该值,满足业务需求
更多应用场景和功能,大家可以多动手动脑