集成 grpc,普通对象与 grpc 对象转换
分布式开发涉及到远程过程调用即 RPC。需要集成 grpc。但如果想无缝集成,则涉及到普通的请求对象转换为 grpc 请求对象。
由于 null 不能序列化,所以 grpc 的对象属性都会有默认值,这在开发中,很难区分,到底请求传的是默认值还是请求本身携带的值。所以使用 protocol buffers 的 oneof 关键字,用于规避默认值。
新建员工类
package com.dld.hll.financial;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Author yue chao
* @Date 2019/8/10 0010 下午 21:23
*/
public class EmpOne {
private Long empIdOne;
private String empNameOne;
private Boolean empSexOne;
private Long totalAssetOne;
private List<String> skills;
private Set<Integer> lucks;
private Map<String, String> relations;
private Date bornDate;
private Timestamp createTime;
private BigDecimal salary;
private DeptOne dept;
// ... 省略 get set
}
新建部门类
package com.dld.hll.financial;
/**
* @Author yue chao
* @Date 2019/8/10 0010 下午 21:24
*/
public class DeptOne {
private Long deptIdOne;
private String deptNameOne;
private Byte deptTypeOne;
// 省略 get set
}
proto 文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.dld.hll.financial.grpc";
option java_outer_classname = "EmpProto";
message EmpOne {
oneof oneof_empId {int64 empIdOne = 4;}
oneof oneof_totalAssetOne {int64 totalAssetOne = 8;}
oneof oneof_empName {string empNameOne = 5;}
oneof oneof_empSex {bool empSexOne = 6;}
DeptOne dept = 7;
repeated string skills = 9;
repeated int32 lucks = 10;
map<string, string> relations = 11;
oneof oneof_bornDate {string bornDate = 12;}
oneof oneof_createTime {string createTime = 13;}
oneof oneof_salary {string salary = 14;}
}
message DeptOne {
oneof oneof_deptId {int32 deptIdOne = 4;}
oneof oneof_deptName {string deptNameOne = 5;}
oneof oneof_deptType {int32 deptTypeOne = 6;}
}
单元测试代码
package com.dld.hll.financial;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.protobuf.util.JsonFormat;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @Author yue chao
* @Date 2019/8/12 0012 上午 11:40
*/
public class EmpOneTest {
/**
* oneof 普通请求转 grpc 请求,再转普通请求
* @throws IOException
*/
@Test
public void testOneCommonRequestTransformToGrpcRequest() throws IOException {oneCommonRequestTransformToGrpcRequest();
}
public static void oneCommonRequestTransformToGrpcRequest() throws IOException {DeptOne dept = new DeptOne();
dept.setDeptIdOne(0L);
dept.setDeptNameOne(StringUtils.EMPTY);
dept.setDeptTypeOne((byte)0);
List<String> skills = new ArrayList<>();
skills.add("EDVSD");
Set<Integer> lucks = new HashSet<>();
EmpOne emp = new EmpOne();
emp.setEmpIdOne(0L);
emp.setEmpNameOne(StringUtils.EMPTY);
emp.setEmpSexOne(false);
emp.setDept(dept);
emp.setSkills(skills);
emp.setLucks(lucks);
emp.setBornDate(new java.sql.Date(System.currentTimeMillis()));
emp.setCreateTime(new java.sql.Timestamp(System.currentTimeMillis()));
emp.setSalary(new BigDecimal("22.33"));
Gson gson = new GsonBuilder().serializeNulls()
.setPrettyPrinting()
.registerTypeAdapter(java.sql.Timestamp.class, new TimeStampGSON())
.registerTypeAdapter(java.sql.Date.class, new SqlDateGSON())
.create();
String empJson = gson.toJson(emp);
System.out.println("普通对象 json==============");
System.out.println(empJson);
com.dld.hll.financial.grpc.EmpOne.Builder builder = com.dld.hll.financial.grpc.EmpOne.newBuilder();
JsonFormat.parser().merge(empJson, builder);
com.dld.hll.financial.grpc.EmpOne empOneGrpc = builder.build();
StringBuilder sb = new StringBuilder();
JsonFormat.printer()
.includingDefaultValueFields() // 设置采用默认值,当集合为空的时候会使用 [] 表示,map 为空的时候采用{},这样可能有效防止直接使用而遇到的空指针
.appendTo(empOneGrpc, sb);
System.out.println("grpc 对象 Json==============");
// 可以观察到普通对象 json 与 grpcJson 的区别,grpcJson 对象字段为 null 的字段不显示, 集合或 map 为空,则使用以上规则处理了
System.out.println(sb);
Gson gson2 = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.registerTypeAdapter(java.sql.Timestamp.class, new TimeStampGSON())
.registerTypeAdapter(java.sql.Date.class, new SqlDateGSON())
.create();
EmpOne vo = gson2.fromJson(sb.toString(), EmpOne.class);
System.out.println("普通对象 json==============");
System.out.println(gson2.toJson(vo));
}
}
测试结果
普通对象 json==============
{
"empIdOne": 0,
"empNameOne": "","empSexOne": false,"totalAssetOne": null,"skills": ["EDVSD"],"lucks": [],"relations": null,"bornDate":"2019-08-12","createTime":"2019-08-12 13:39:14","salary": 22.33,"dept": {"deptIdOne": 0,"deptNameOne":"",
"deptTypeOne": 0
}
}
grpc 对象 Json==============
{
"empIdOne": "0",
"empNameOne": "","empSexOne": false,"dept": {"deptIdOne": 0,"deptNameOne":"",
"deptTypeOne": 0
},
"skills": ["EDVSD"],
"lucks": [],
"relations": { },
"bornDate": "2019-08-12",
"createTime": "2019-08-12 13:39:14",
"salary": "22.33"
}
普通对象 json==============
{
"empIdOne": 0,
"empNameOne": "","empSexOne": false,"totalAssetOne": null,"skills": ["EDVSD"],"lucks": [],"relations": {},"bornDate":"2019-08-12","createTime":"2019-08-12 13:39:14","salary": 22.33,"dept": {"deptIdOne": 0,"deptNameOne":"",
"deptTypeOne": 0
}
}