Google Buffer代码生成工具

        在使用GOOGLE BUFFER的时候经常要编写存根在生成类,而有往往和数据库通信的实体类又要独立出来,怎么办了能不能通过实体类来生成PROTO存根文件,在通过调用protoc.exe来生成BUFFER类了,为了提高开发效率最近就用JAVA的反射技术和JAVA的注解技术来编写了一个小工具,专门从实体到存根在从存根到BUFFER的工具类。

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) 
public @interface Proto {
	String protoPackage() default "";
	String packageName() default "";
	String className() default "";
	boolean subClass() default false;
}

类注解

package com.buffer.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) 
public @interface Fields {
	String fieldType() default "required";
	String fieldName() default "";
	String protoType() default "";
	String mapping() default "";
	int fieldIndex() default -1;
	String defValue() default "";
	String enums() default "";
}
                                                                                                                                                     字段注解


package com.buffer.transform;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;

import com.buffer.annotation.Fields;
import com.buffer.annotation.Proto;
import com.buffer.util.TypeHandler;


public class JavaTransformProtos {
	
	private String srcClassPath = "";
	
	private String protoFilePath = "";
	
	private String protoFileName = "";
	
	private String projectDir = "";
	
	private String classPackage = "";
	
	public JavaTransformProtos(String classPackage, String protoFileDir) throws Exception {
		File currentFile = new File("");
		projectDir = currentFile.getCanonicalPath();
		this.classPackage = classPackage;
		System.out.println(classPackage);
		this.srcClassPath = projectDir + "/src/" + classPackage.replace(".", "/");;
		System.out.println(srcClassPath);
		this.protoFilePath = projectDir + "/" + protoFileDir;
		File protoDir = new File(this.protoFilePath);
		if(!protoDir.isDirectory()) {
			protoDir.mkdirs();
		}
	}
	
	public void startTransform() throws Exception {
		File pojoPackage = new File(srcClassPath);
		for(String classFile : pojoPackage.list()) {
			String className = classFile.substring(0, classFile.indexOf("."));
			System.out.println(className);
			Class<?> clazz = Class.forName(classPackage + "." + className);
			System.out.println(clazz.getName());
			Proto proto = clazz.getAnnotation(Proto.class);
			if(proto != null && !proto.subClass()) {
				String protoFile = transform(clazz);
				if(protoFile != null) {
					System.out.println(protoFile);
					protoFileName = clazz.getSimpleName() + "Proto.proto";
					System.out.println(protoFilePath + "/" + protoFileName);
					File writeProtoFile = new File(protoFilePath + "/" + protoFileName);
					FileOutputStream out = new FileOutputStream(writeProtoFile);
					out.write(protoFile.getBytes());
					out.flush();
					out.close();
				}
			}
		}
		buildJava();
	}
	
	public void buildJava() throws Exception {
		Runtime run = Runtime.getRuntime();
		BufferedReader reader = null;
		File file = new File(protoFilePath);
		for(String protoName : file.list()) {
			System.out.println(protoName);
			String commend = projectDir + "/protoc.exe -I=" + protoFilePath + " --java_out=" + projectDir + "/src/" + " " +  protoFilePath + "/" + protoName;
			System.out.println(commend);
			Process process = run.exec(commend);
			reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
			String line = null;
			while((line = reader.readLine()) != null) {
				System.out.println(line);
			}
		}
		
	
	}

	private String transform(Class<?> clazz) throws Exception {
		Proto proto = clazz.getAnnotation(Proto.class);
		if(proto != null) {
			String protoFile = "";
			String protoPackage = "";
			String packageName = "";
			String className = "";
			if(!proto.subClass()) {
				if(!proto.protoPackage().equals("")) {
					protoPackage = "package " + proto.protoPackage() + ";\n";
				}
				if(!proto.packageName().equals("")) {
					packageName = "option java_package = \"" + proto.packageName() + "\";\n";
				} else {
					System.out.println("default:" + clazz.getPackage());
					packageName = "option java_package = \"" + clazz.getPackage() + "\";\n";
				} 
				if(!proto.className().equals("")) {
					className = "option java_outer_classname = \"" + proto.className() + "\";\n";
				} else {
					System.out.println("default:" + clazz.getSimpleName());
					className = "option java_outer_classname = \"" + clazz.getSimpleName() + "\";\n";
				}
			}
			String messageName = "message " + clazz.getSimpleName() + " {\n";
			String protoFields = "";
			String subProto = "";
			String enumType = "";
			int defaultIndex = 1;
			for(Field field : clazz.getDeclaredFields()) {
				String protoField = "";
				Fields fieldAnno = field.getAnnotation(Fields.class);
				if(fieldAnno != null) {
					
				String fieldType = fieldAnno.fieldType();
				String fieldName = fieldAnno.fieldName();
				String protoType = fieldAnno.protoType();
				int index = fieldAnno.fieldIndex();
				String mapping = fieldAnno.mapping();
				String defValue = fieldAnno.defValue();
				String enums = fieldAnno.enums();
				
					if(!fieldType.equals("")) {
						protoField += fieldType;
					}
					
					if(!protoType.equals("")) {
						protoField += " " + protoType;
					} else if(enums.equals("") && mapping.equals("")){
						protoType = TypeHandler.getProtoType(field.getType().getName());
						if(protoType == null) {
							throw new Exception("@Fields mapping error Class can not find");
						}
						protoField += " " + protoType;
					} else if(!enums.equals("")){
						Class<?> enumClass = Class.forName(enums);
						int enumIndex = 1;
						String enumName = enumClass.getSimpleName();
						enumType = "enum " + enumName + " {\n";
						
						for(Field enumField : enumClass.getFields()) {
							enumType += enumField.getName() + "=" + enumIndex + ";\n";
							enumIndex++;
						}
						enumType += "}\n";
						protoFields += enumType;
						protoField += " " + enumName;
					}
					
					if(!mapping.equals("")) {
						Class<?> mappingClazz = Class.forName(mapping);
						subProto = transform(mappingClazz);
						protoFields += subProto;
						protoField += " " + mappingClazz.getSimpleName();
					}
					
					if(!fieldName.equals("")) {
						protoField += " " + fieldName;
					} else {
						protoField += " " + field.getName(); 
					}
					
					if(index != -1) {
						protoField += " = " + index;
					} else {
						protoField += " = " + defaultIndex; 
					}
					
					if(!defValue.equals("")) {
						switch(protoType) {
							case "string" : {
								defValue = "\"" + defValue + "\"";
								break;
							}
							case "float" : {
								defValue = "" + Float.parseFloat(defValue);
								break;
							}
							case "double" : {
								defValue = "" + Double.parseDouble(defValue);
								break;
							}
							case "int32":
							case "int64": {
								defValue = "" + Integer.parseInt(defValue);
								break;
							}
						}
						protoField += " [default = " + defValue + "]";
					}
	
					protoFields += protoField +";\n";
					protoField = "";
					defaultIndex++;
				}
			}
			protoFile = protoPackage + packageName + className + messageName + protoFields;
			protoFile += "}\n";
			return protoFile;
		} else {
			return null;
		}
	}
	
	public static void main(String[] args) throws Exception {
		JavaTransformProtos jtp = new JavaTransformProtos("com.pojo", "proto");
		jtp.startTransform();
	}
}

处理类
package com.buffer.util;

import java.util.HashMap;
import java.util.Map;


public class TypeHandler {

	private static Map<String, String> typeMap = new HashMap<String, String>();
	
	static {
		typeMap.put("byte", "int32");
		typeMap.put("java.lang.Byte", "int32");
		typeMap.put("short", "int32");
		typeMap.put("java.lang.Short", "int32");
		typeMap.put("int", "int32");
		typeMap.put("java.lang.Integer", "int32");
		typeMap.put("long", "int64");
		typeMap.put("java.lang.Long", "int64");
		typeMap.put("float", "float");
		typeMap.put("java.lang.Float", "float");
		typeMap.put("double", "double");
		typeMap.put("java.lang.Double", "double");
		typeMap.put("java.lang.String", "string");
		typeMap.put("boolean", "bool");
		typeMap.put("java.lang.Boolean", "bool");
		typeMap.put("com.google.protobuf.ByteString", "bytes");
	}
	
	public static String getProtoType(String javaType) {
		System.out.println(javaType);
		return typeMap.get(javaType);
	}
}
基本对象类型映射
package com.pojo;

import java.util.ArrayList;
import java.util.List;

import com.buffer.annotation.Fields;
import com.buffer.annotation.Proto;

@Proto(protoPackage="com.test", packageName="com.pojo", className="MemberOrder")
public class Member {

	@Fields
	private long uid;
	
	@Fields(fieldType="optional", fieldName="username", protoType="string", fieldIndex=2, defValue="134567")
	private String username;
	
	@Fields
	private String password;
	
	@Fields(fieldType="repeated", mapping="com.pojo.Order")
	private List<Order> orders = new ArrayList<Order>();

	public long getUid() {
		return uid;
	}

	public void setUid(long uid) {
		this.uid = uid;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public List<Order> getOrders() {
		return orders;
	}

	public void setOrders(List<Order> orders) {
		this.orders = orders;
	}
	
}
测试类1
package com.pojo;

import com.buffer.annotation.Fields;
import com.buffer.annotation.Proto;

@Proto(subClass=true)
public class Order {

	@Fields(fieldType="required", fieldName="orderId", protoType="int32", fieldIndex=1)
	private int orderId;
	
	@Fields(fieldType="optional", fieldName="productName", protoType="string", fieldIndex=2)
	private String productName;

	@Fields(enums="com.pojo.OrderType", defValue="BUY")
	private OrderType orderType; 
	
	private Member member;

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public Member getMember() {
		return member;
	}

	public void setMember(Member member) {
		this.member = member;
	}

	public OrderType getOrderType() {
		return orderType;
	}

	public void setOrderType(OrderType orderType) {
		this.orderType = orderType;
	}
}
测试类2
package com.pojo;

public enum OrderType {
	GROUPBUY,
	BUY
}
测试类3
使用方法在你的工程的ENTITY对象上加上注解,在构造方法中传入ENTITY对象的包路径格式为 例:com.entity  在传入存根要存放的位置 ,运行程序就可以在类注解指定的包中生成BUFFER类,请一定要将protoc.exe拷贝到项目根目录下。如我的项目名称是bufferTools那么就拷贝到这个目录下。







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值