0
点赞
收藏
分享

微信扫一扫

基于grpc从零开始搭建一个准生产分布式应用(6) -04- MapStruct-proto映射

大多数与java普通类转换类型,所以这小节只描述一些特殊的点

一、通用模板

 @Mapper
public class BaseMapper {
@ObjectFactory
public ProtocolStringList createProtocolStringList(List<String> list) {
return new LazyStringArrayList(list.size());
}

public static byte[] toByte(ByteString bytes) {
return bytes.toByteArray();
}
}

@Mapper(uses = {ByteString.class, BaseMapper.class}, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {
Test toProto(TestDTO testDTO);
TestDTO toDTO(Test test);
}

​不能更新protobuf对象,更新总是会clear-get-addAll。使用protobuf的builder对象操作时,其中一个原因List<Long>类型的实现是一个UnmodifiableRandomAccessList,mapstruct在更新list时会clear集合,使用会抛异常。使用protobuf对象而非builder时,集合是一个EmptyList,增删改查也会抛异常。

protobuf3中不再有基础属性类型的hasXXX检查,使用string类型默认值是“”,转换可能会有NPE,比如转Date,这里只有手动指定expression转换 testDTO.setCreateTime( BaseMapper.toDateFromString(test.getCreateTime(), "yyyy-mm-dd") );

二、带有Any类型的映射

message Test3 {
map<string, string> kv = 9;
oneof test_oneof {----------
string one_string = 10;
int32 one_int = 11;
}
google.protobuf.Any details = 15;----------
}
@Mapper
public class BaseMapper {

@ObjectFactory
public ProtocolStringList createProtocolStringList(List<String> list) {
return new LazyStringArrayList(list.size());
}

public static byte[] toByte(ByteString bytes) {
return bytes.toByteArray();
}

public static ByteString copyFrom(byte[] bytes) {
return ByteString.copyFrom(bytes);
}

// any转javabean的中间转换方法
public static <T extends GeneratedMessageV3> T unpack(Any any, @TargetType Class<T> clazz) {
T unpack;
try {
unpack = any.unpack(clazz);
} catch (InvalidProtocolBufferException e) {
return null;
}
return unpack;
}

// 这里只是为了在mapstruct编译找最合适方法时中间的过渡,并不是直接调用,但一定要加,具体分析参见第12.6章
public static <T extends GeneratedMessageV3> Any pack(T message) {
return Any.pack(message);
}

// protobuf转javabean的中间转换方法
public static Any packGeneratedMessageV3(GeneratedMessageV3 message) {
return Any.pack(message);
}

public static Date toDateFromString(String dateString, String format) {
if (StringUtils.isEmpty(dateString)) {
return null;
}
Date date;
try {
date = new SimpleDateFormat(format).parse(dateString);
} catch (ParseException e) {
return null;
}
return date;
}

}

@Mapper(uses = { BaseMapper.class}, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface TestMapper {

Test3 toProto(Test3DTO test3DTO);

// 对象属性的转换一定要手动定义方法
Item3 toProtoItem(ItemDTO itemDTO);

@Mapping(target = "createTime", expression = "java(BaseMapper.toDateFromString(test.getCreateTime(), \"yyyy-mm-dd\"))")
Test3DTO toDTO(Test3 test);

// 对象属性的转换一定要手动定义方法
ItemDTO toItemDTO(Item3 item3);

@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
TypeEnum toTypeEnum(DownloadResourceTypeEnum downloadResourceTypeEnum);

}

三、Date类型映射

mapstrut默认为getSeconds()这个是有问题的
Date转化为com.google.protobuf.Timestamp
Timestamp a = Timestamps.fromMillis(new Date().getTime());

com.google.protobuf.Timestamp转化为Date:
Timestamp timestamp = null;
Date date = new Date(timestamp.getSeconds() * 1000);

举报

相关推荐

0 条评论