protobuf的优势这里就不细说了,这里给java开发童鞋们分享一个可以将普通java对象转换成.proto生成的java对象的方法,大家在编写完.proto文件后生成java对象后,肯定都遇到过一个问题,就是不同的对象构造方法不一样,以下为本人写的一个通用方法:
/**
* 该方法将javabean对象转换成protobuf对应的bean
*
* @param javaBean
* @param protoBuilder
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Object javaBeanToProtoBean(Object javaBean, Object protoBuilder) {
try {
Method mm = protoBuilder.getClass().getMethod("getDescriptorForType");
Descriptors.Descriptor descriptor = (Descriptor) mm.invoke(protoBuilder);
Field[] fields = javaBean.getClass().getDeclaredFields();
for (Field item : fields) {
try{
String fName = item.getName();
item.setAccessible(true);
Object jObject = item.get(javaBean);
if(null == jObject){
break;
}
FieldDescriptor fd = descriptor.findFieldByName(fName);
if(null != fd){
if(fd.isRepeated()){
boolean isDefined = false;
Method[] mmm = protoBuilder.getClass().getMethods();
for(Method mItem : mmm){
try{
String mName = mItem.getName();
String mName1 = "add" + StringUtil.firstToUpperCase(fName);
if(mName1.equals(mName) && mItem.getParameterTypes().length == 1){
Class[] ccList = mItem.getParameterTypes();
Class cc = ccList[0];
Method me = cc.getMethod("newBuilder");
Object oBuilder = me.invoke(null);//获取自定义对象builder
List<Object> dList = (List<Object>) jObject; //数据为List集合
List<Object> pBeanList = new ArrayList<Object>();
for(Object oItem : dList){
Object pBean = javaBeanToProtoBean(oItem,oBuilder);
pBeanList.add(pBean);
}
Method mee = protoBuilder.getClass().getMethod("addAll"+StringUtil.firstToUpperCase(fName),Iterable.class);
mee.invoke(protoBuilder, pBeanList);
isDefined = true;
}
}catch(Exception e){
}
}
if(!isDefined){
try{
Method me = protoBuilder.getClass().getMethod("addAll"+StringUtil.firstToUpperCase(fName),Iterable.class);
me.invoke(protoBuilder, jObject);
}catch(Exception e){
LOG.info("this repeated field is a user-defined field");
e.printStackTrace();
}
}
}else{
boolean isDefined1 = false;
try{
//自定义对象继续需要通过builder来解析处理,回调
Method bM = protoBuilder.getClass().getMethod("getFieldBuilder", FieldDescriptor.class);
Object subBuilder = bM.invoke(protoBuilder, fd);
Object pBean = javaBeanToProtoBean(jObject,subBuilder);
Method me = protoBuilder.getClass().getMethod("setField", FieldDescriptor.class, Object.class);
me.invoke(protoBuilder, fd, pBean);
isDefined1 = true;
}catch(Exception e){
LOG.info("this required field is not a user-defined field");
}
if(!isDefined1){
Method me = protoBuilder.getClass().getMethod("setField", FieldDescriptor.class, Object.class);
me.invoke(protoBuilder, fd, jObject);
}
}
}
}catch(Exception e){
LOG.error("javaBeanToProtoBean method item reflect error, item name:"+item.getName());
}
}
Method buildM = protoBuilder.getClass().getMethod("build");
Object rObject = buildM.invoke(protoBuilder);
/* Method byteM = rObject.getClass().getMethod("toByteArray");
Object byteObject = byteM.invoke(rObject);
byte[] pbByte = (byte[]) byteObject;
String pbStr = new String(Base64.getEncoder().encode(pbByte), "UTF-8");*/
return rObject;
} catch (Exception e) {
e.printStackTrace();
LOG.error("convert javabean to protobuf bean error,e:", e);
return null;
}
}
此方法入参和返回结果都是Object类型,可以适用不同类型java对象 ,
public static Object javaBeanToProtoBean(Object javaBean, Object protoBuilder)
javaBean是已知普通java对象,protoBuilder是proto对象生成的builder 返回结果就是protoBuilder.build()出来的对象
注:编写的proto文件格式与javaBean对象要严格一一对应(参数名称和结构)