从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));
}
}