/**
* Created by jay.zhou on 2018/7/17.
*/
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
/**
* 用于操作某个实体的属性的工具类
*/
public abstract class FieldUtils<T> {
/**
* @param entity 要被操作的数据实体
* @param className 要被操作的属性的类全限定名
* @param pattern 数据精度,如果操作的属性是数值类型,那么表示具体保留几位小数
* @param args 额外参数列表
* @return 操作的结果集
*/
public Map handler(T entity, String className,Integer pattern, Object... args) {
//前处理骨架
preHandler();
//获取类的字节码文件
Class clazz = entity.getClass();
//获取类中所有的属性
Field[] field = clazz.getDeclaredFields();
//处理具体的属性
Map map = handlerField(field, entity, className,pattern, args);
//后处理骨架
postHandler();
return map;
}
/**
* 操作集合中的数据
* 比如List<T>中携带需要的类型
*
* @param list 要被操作的数据实体
* @param className 要被操作的属性的类全限定名
* @param pattern 数据精度,如果操作的属性是数值类型,那么表示具体保留几位小数
* @param args 额外参数列表
* @return 操作的结果集
*/
public abstract List handlerList(List<? extends T> list, String className, Integer pattern ,Object... args) ;
/**
* 前处理
*/
protected abstract void preHandler();
/**
* 后处理
*/
protected abstract void postHandler();
/**
* 强制子类重写的方法,用于操作实体中指定类型的属性
*
* @param field 实体的属性数组Field[]
* @param entity 实体元素
* @param className 要被操作的属性的类全限定名
* @param pattern 数据精度,如果操作的属性是数值类型,那么表示具体保留几位小数
* @param args 额外参数列表
* @return 操作的结果集,采用map集合进行数据传递
*/
protected abstract Map<String, Object> handlerField(Field[] field, T entity, String className, Integer pattern,Object[] args);
}
import org.slf4j.Logger;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Created by jay.zhou on 2018/7/17.
*/
public final class ReceiptFieldUtils extends FieldUtils<BaseEntity> {
private static final Logger LOGGER = getLogger(ReceiptFieldUtils.class);
/**
* 对List集合中的所有实体进行属性格式化
* 参考handlerField()方法
*
* @param list 要被操作的数据实体
* @param className 要被操作的属性的类全限定名
* @param pattern 数据精度,如果操作的属性是数值类型,那么表示具体保留几位小数
* @param args 额外参数列表
* @return 返回一个list, 存放的是每个实体的处理后的map集合
*/
@Override
public List handlerList(List<? extends BaseEntity> list, String className, Integer pattern,Object... args) {
//构造返回结果集
List<Map> result = new ArrayList<>();
//健壮性判断,如果用户传递的list为空,那么就直接返回null
if (list == null) {
return null;
}
//对于每个要被操作的属性,调用handlerField()方法进行格式化
for (BaseEntitydomain : list) {
Map map = handler(domain, className,pattern, args);
result.add(map);
}
return result;
}
/**
* 调用本方法后的示例
* 如果有一个账单实体,
* 持有进货数量属性in 与 出货数量属性out,其值分别为 1000、2000,类型为BigDecimal
* 另外还只有一个流水号id,值为3000,属性类型为Long
* 所以账单实体为: {in:1000, out:2000 , id:3000}
* 调用父类工具类FieldUtils的handler方法
* handler(账单实体,java.math.BigDecimal,4);
* 返回的map为: {in:1,000.0000 , out:2,000.0000 , id:3000}
* 因为流水号id的类型为Long,而方法操作的类型为BigDecimal类型,所以id的值没有被处理
*
* @param field 实体的属性数组Field[]
* @param entity 实体元素
* @param className 要被操作的属性的类全限定名
* @param args 额外参数列表
* @return 一个map集合,对指定格式的属性进行转化,其它格式的属性保留原来的值
*/
@Override
protected Map handlerField(Field[] field, AbstractBaseDomain entity, String className, Integer pattern,Object[] args) {
Map<String, Object> map = new HashMap<>();
//先通过遍历此实体的所有属性
for (Field f : field) {
//暴力访问,为了获取private属性的值,这个值已经从数据库中获取了
f.setAccessible(true);
//判断属性的类型
String type = f.getGenericType().toString();
//如果是指定的类型,金额类的都是BigDecimal
if (type.equals("class " + className)) {
//那么就将其格式化,并存储到map中
//第一步先获取字段名称
String filedName = f.getName();
//下面是用来格式化数据
NumberFormat nfs = NumberFormat.getNumberInstance(Locale.CHINA);
//这里可能出现异常,如果用户未传递精度,将导致空指针异常
if(pattern == null){
//默认采用保留两位小数的精度
pattern = 2;
}
//具体保留几位,设置最小保留长度与最大保留长度一样,那么就会保留几位
nfs.setMinimumFractionDigits(pattern);
nfs.setMaximumFractionDigits(pattern);
//实体的属性的值
Object obj;
try {
//暴力获取值
obj = f.get(entity);
//转型
BigDecimal bigDecimal = (BigDecimal) obj;
//健壮性判断
if (bigDecimal == null) {
continue;
}
//转为double类型,准备通过格式化工具转型
double value = bigDecimal.doubleValue();
//格式化并放入map中
String str = nfs.format(value);
//filedName为实体的属性名,str为实体属性对应的值
map.put(filedName, str);
} catch (IllegalAccessException e) {
LOGGER.error("获取私有字段出现错误!", e);
}
} else {
//如果当前要操作的属性不是我们指定的属性
//还要保留以前的其它属性值
//获取字段名称
String filedName = f.getName();
//暴力获取值
Object obj;
try {
obj = f.get(entity);
map.put(filedName, obj);
} catch (IllegalAccessException e) {
LOGGER.error("获取私有字段出现错误!", e);
}
}
}
return map;
}
@Override
protected void preHandler() {
}
@Override
protected void postHandler() {
}
}