如何优雅的反射得到Bean,无视属性类型

17 篇文章 0 订阅

从hbase中得到了scan结果如果不用spring hbase 模块如何自己实现解析。
这个是在使用hbase中的一个难题。

下面就用 hbase中的结果作为实例,展示一下。如果有更好的方法,请回复哦,相互学习。
该解析工具类经过几次抽象迭代,得到的结果,通用性很高,特来分享下。
在github 中也有完整的使用,请查收,欢迎follow。


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;

/**
 * 
 * 解析工具,对代码进行抽取,避免bean类型的依赖,提高代码的通用性 如何优雅的反射出一个对象
 * 
 * @author sh04595 20171220
 * 
 * @param <T> Bean Type
 */
public class ParserUtils<T> {

    // private static final Field[] fields = User.class.getDeclaredFields();
    // private static final String keyField = "userId";

    // private static final byte[] family = Bytes.toBytes("f1");
    // private static final byte[] col_name = Bytes.toBytes("name");
    // private static final byte[] col_age = Bytes.toBytes("age");

    /**
     * 优雅解析User,根据bean属性类型自动判断处理赋值问题
     * 
     * @param rs
     *            scan result
     * @param clazz
     *            bean class
     * @param keyField
     *            table中key对应的属性
     * @return bean
     * @throws Exception
     */
    public static <T> T parser2Bean(Result rs, Class<T> clazz, String keyField)
            throws Exception {
        Field[] fields = clazz.getDeclaredFields();
        List<Cell> listCells = rs.listCells();

        T user = clazz.newInstance();
        // 遍历key对应的所有Cell
        for (Cell cell : listCells) {
            String key = Bytes.toString(CellUtil.cloneRow(cell));

            // String cloneFamily = Bytes.toString(CellUtil.cloneFamily(cell));
            // // 列簇名
            String cloneQualifier = Bytes.toString(CellUtil
                    .cloneQualifier(cell)); // 列名
            String cloneValue = Bytes.toString(CellUtil.cloneValue(cell)); // 列值

            for (Field field : fields) { // 遍历所有的属性
                //Object value = null;
                String fieldName = field.getName();

                // 处理key对应的属性
                if (fieldName.equalsIgnoreCase(keyField)) {
                    // 此處可以賦值也可以不賦值,引用改變
                    user = invokField(clazz, keyField, user, key, field);
                } else if (fieldName.equalsIgnoreCase(cloneQualifier)) {
                    invokField(clazz, fieldName, user, cloneValue, field);
                    break;
                }
            }
        }
        return user;
    }

    /**
     * 根據具體的屬性進行處理
     * @param clazz
     * @param keyField
     * @param user
     * @param key
     * @param field
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static <T> T invokField(Class<T> clazz, String keyField, T user,
            String key, Field field) throws NoSuchMethodException,
            IllegalAccessException, InvocationTargetException {
        Object value;
        String mathodName = "set" + toUpperCase4Index(keyField);
        value = getFieldValue(key, field);
        Method keymethod = clazz.getMethod(mathodName, field.getType());
        keymethod.invoke(user, value); // 执行反射,对属性进行set vale
        return user;
    }

    /**
     * 根据需要传入的value 解析成制定的类型的Object,比如 Double,Integer ref
     * https://www.zhihu.com/question/67687909
     * 
     * @param sValue
     *            source string value
     * @param field
     *            object field
     * @return field relevant value
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static Object getFieldValue(String sValue, Field field)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
        Object value = null;
        Class<?> fieldType = field.getType();
        if (fieldType == String.class)
            value = sValue;
        else {
            Method methodType = fieldType.getMethod("parse"
                    + fixparse(fieldType.getSimpleName()), String.class);
            value = methodType.invoke(null, sValue);
        }
        return value;
    }

    /**
     * 当属性为 Integer的时候特殊处理
     * 
     * @param fstype
     * @return
     */
    private static String fixparse(String fstype) {
        switch (fstype) {
        case "Integer":
            return "Int";
        default:
            return fstype;
        }
    }

    /**
     * 首字母大写
     * 
     * @param string
     * @return
     */
    public static String toUpperCase4Index(String string) {
        char[] methodName = string.toCharArray();
        methodName[0] = toUpperCase(methodName[0]);
        return String.valueOf(methodName);
    }

    /**
     * 字符转成大写
     * 
     * @param chars
     * @return
     */
    public static char toUpperCase(char chars) {
        if (97 <= chars && chars <= 122) {
            chars ^= 32;
        }
        return chars;
    }
}

当然写入hbase中也是有一套解决方案,不用硬代码生成put。
下面是实例,目前还没放到github上。

private static final byte[] CF_INFO = Bytes.toBytes("cfInfo");
private static final Field[] fields = VhlData.class.getDeclaredFields();
for (Field field : fields) {
                    String fieldName = field.getName();
                    String fieldValue = (String) field.get(vhlData);
                    if (fieldValue != null && fieldValue.length() > 0) {
                        p.add(CF_INFO, Bytes.toBytes(fieldName), Bytes.toBytes(fieldValue));
                    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mtj66

看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值