pojo 에 대한 protobuf 의 직접 디 코딩 실현
https://developers.google.com/protocol-buffers/docs/overview에서 말 한 것 은 먼저 protoc 컴 파일 러 로 대응 하 는 언어의 디 코딩 대 리 를 만 든 다음 에 프 록 시 build 와 parse 데 이 터 를 사용 해 야 합 니 다.
내 응용 장면 에서 스 크 립 트 를 사용 하여 설정 에 따라 자바 pojo 소스 코드 와 대응 하 는 proto 파일 을 직접 생 성하 고 pojo 에 자신의 디 코딩 방법 을 추가 합 니 다.이렇게 되면 protoc 를 호출 하여 프 록 시 를 만 드 는 전략 을 사용 하 는 것 이 매우 서 툴 러 보 입 니 다.또한 protobuf 가 프 록 시 클래스 로 인 코딩 데 이 터 를 풀 수 있 으 니 이론 적 으로 직접 인 코딩 데 이 터 를 만 드 는 것 도 가능 하지만 안 타 깝 게 도 구 글 은 이러한 문서 설명 을 제공 하지 않 았 습 니 다.
구 글 을 거 친 후,stackoverflow 에 서 는 Descriptor 가 proto 파일 을 묘사 하고,C++로 이 루어 진 직접 디 코딩 코드 도 있 습 니 다.자바 쪽 은 매우 적 습 니 다.한 친구 만 공유 할 수 있 습 니 다.
감사 드 립 니 다.
다음은 디 코딩 코드 의 실현 입 니 다.
package miniserver.util;
import static miniserver.util.ReflectionUtil.gatherAllFields;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorSet;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.DynamicMessage.Builder;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
public class ProtoParserOrBuilder {
private Map<String, Descriptor> descriptors = null;
private static final String TEMP_DIR = "D://";
public static final String PROTOC_PATH = System.getProperty("user.dir")
+ "/protoc/protoc.exe";
private File descFile;
public ProtoParserOrBuilder() {
descriptors = new HashMap<String, Descriptor>();
}
public ProtoParserOrBuilder(File proto) {
descriptors = new HashMap<String, Descriptor>();
init(proto);
}
private void init(File proto) {
if (descFile != null && descFile.exists()) {
descFile.delete();
}
this.descFile = createDescripFile(proto);
FileInputStream fin = null;
try {
fin = new FileInputStream(descFile);
FileDescriptorSet descriptorSet = FileDescriptorSet.parseFrom(fin);
for (FileDescriptorProto fdp : descriptorSet.getFileList()) {
FileDescriptor fd = FileDescriptor.buildFrom(fdp,
new FileDescriptor[] {});
for (Descriptor descriptor : fd.getMessageTypes()) {
String className = descriptor.getName();
this.descriptors.put(className, descriptor);
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DescriptorValidationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (fin != null) {
fin.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private File createDescripFile(File proto) {
try {
Runtime run = Runtime.getRuntime();
String descFileName = System.currentTimeMillis()
+ "FastProtoParser.desc";
String protoPath = proto.getCanonicalPath();
String protoFPath = proto.getParentFile().getAbsolutePath();
String cmd = PROTOC_PATH + " -I=" + protoFPath
+ " --descriptor_set_out=" + TEMP_DIR + descFileName + " "
+ protoPath;
System.out.println(cmd);
// , desc
Process p = run.exec(cmd);
if (p.waitFor() != 0) {
if (p.exitValue() == 1) {// p.exitValue()==0 ,1:
throw new RuntimeException("protoc ");
}
}
return new File(TEMP_DIR + descFileName);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public <T> T parse(Class<T> clazz, byte[] bytes) {
String className = clazz.getSimpleName();
Descriptor desc = this.descriptors.get(className);
Map<String, String> fields = new HashMap<String, String>();
try {
DynamicMessage message = DynamicMessage.parseFrom(desc, bytes);
Map<FieldDescriptor, Object> fieldDescs = message.getAllFields();
for (Map.Entry<FieldDescriptor, Object> entry : fieldDescs
.entrySet()) {
fields.put(entry.getKey().getName(), entry.getValue()
.toString());
}
T instance = clazz.newInstance();
List<Field> fieldList = ReflectionUtil.gatherAllFields(clazz);
for (Field f : fieldList) {
ReflectionUtil.fillField(fields, instance, f);
}
return instance;
} catch (InvalidProtocolBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public byte[] build(Object obj) {
Class<? extends Object> clazz = obj.getClass();
String className = clazz.getSimpleName();
Descriptor desc = this.descriptors.get(className);
Builder builder = DynamicMessage.newBuilder(desc);
List<FieldDescriptor> fieldDescs = desc.getFields();
List<Field> fields = gatherAllFields(clazz);
try {
Map<String, Object> fieldValues = new HashMap<String, Object>();
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
Object fieldValueObject;
fieldValueObject = field.get(obj);
if (fieldValueObject != null) {
fieldValues.put(fieldName, fieldValueObject);
}
}
for (FieldDescriptor fieldDesc : fieldDescs) {
String fieldName = fieldDesc.getName();
Object val = fieldValues.get(fieldName);
if (val != null) {
builder.setField(fieldDesc, val);
}
}
Message message = builder.build();
return message.toByteArray();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
this.descFile.delete();
}
}
이미 검증 을 거 쳤 습 니 다.프 록 시 클래스 에서 생 성 된 데이터 와 똑 같 고 해석 에 도 문제 가 없 으 니 안심 하고 사용 하 십시오.
본 보 의 오리지널 사 이 트 는 ITeye 입 니 다.다시 전재 가 있 으 면 출처 를 밝 혀 주 십시오.합작 해 주 셔 서 감사합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.