对实体中的指定类型的实体进行修改

/**
 * 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() {
    }
}

猜你喜欢

转载自blog.csdn.net/yanluandai1985/article/details/81177921