天天看点

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

开始前必读:​基于grpc从零开始搭建一个准生产分布式应用(0) - quickStart​​ 

大多数与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); 
}      

二、带有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);