MapStruct文件(十二)——protobuf對映
目錄
11.1、protobuf2
定義一些基礎類
enum DownloadResourceTypeEnum{ download_resource_type_enum_audio = 0; //音訊 download_resource_type_enum_vedio = 1; //視訊 download_resource_type_enum_picture = 2; //圖片 download_resource_type_enum_txtfile = 3; //txt檔案 download_resource_type_enum_wordfile = 4; //word文件 download_resource_type_enum_excelfile = 5; //excel文件 download_resource_type_enum_pptfile = 6; //ppt文件 download_resource_type_enum_pdffile = 7; //pdf文件 } message Test { optional int32 id = 1; optional string name = 2; optional string create_time = 3; repeated Item item = 4; optional DownloadResourceTypeEnum download_resource_type_enum = 5; optional Item main_item = 6; optional bool disable = 7; optional float pre_price = 8; map<string, string> kv = 9; oneof test_oneof { string one_string = 10; int32 one_int = 11; } repeated string number = 12; repeated DownloadResourceTypeEnum types = 13; repeated int32 nos = 14; } message Item { optional int64 item_id = 1; optional double price = 2; optional uint32 uint32_count = 3; // 對應java int optional uint64 uint64_count = 4; // 對應java Long optional sint32 sint32_count = 5; // 對應java INT 比常規int32更有效地編碼負數 optional sint64 sint64_count = 6; // 對應java long 比常規int64更有效地編碼負數 optional fixed32 fixed32_count = 7; // 對應java int 總是四個位元組。如果值通常大於228,則比uint32更有效 optional fixed64 fixed64_count = 8; // 對應java Long 總是八個位元組。如果值通常大於256,則比uint64更有效 optional sfixed32 sfixed32_count = 9; // 對應java INT 總是四個位元組。 optional sfixed64 sfixed64_count = 10; // 對應java long 總是八個位元組。 optional bytes type = 11; // 不可變的位元組陣列 不涉及轉碼 通常用於傳輸字元流 } @Data public class TestDTO { private Integer id; private String name; private Date createTime; private TypeEnum downloadResourceTypeEnum; private ItemDTO mainItem; private Boolean disable; private BigDecimal prePrice; private Map<String, String> kv; private String oneString; private Integer oneInt; private List<ItemDTO> itemList; private List<String> numberList; private List<TypeEnum> typesList; private List<Integer> nosList; } @Data public class ItemDTO { private Long itemId; private Double price; private Integer uint32Count; private Long uint64Count; private Integer sint32Count; private Long sint64Count; private Integer fixed32Count; private Long fixed64Count; private Integer sfixed32Count; private Long sfixed64Count; private byte[] type; }
使用
@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); }
編譯的結果
@Component public class TestMapperImpl implements TestMapper { @Autowired private ByteString byteString; @Override public Test toProto(TestDTO testDTO) { if ( testDTO == null ) { return null; } Builder test = Test.newBuilder(); if ( testDTO.getId() != null ) { test.setId( testDTO.getId() ); } try { if ( testDTO.getName() != null ) { test.setName( byteString.toString( testDTO.getName() ) ); } } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } if ( testDTO.getCreateTime() != null ) { test.setCreateTime( new SimpleDateFormat().format( testDTO.getCreateTime() ) ); } if ( testDTO.getDownloadResourceTypeEnum() != null ) { test.setDownloadResourceTypeEnum( typeEnumToDownloadResourceEnum( testDTO.getDownloadResourceTypeEnum() ) ); } if ( testDTO.getMainItem() != null ) { test.setMainItem( itemDTOToItem( testDTO.getMainItem() ) ); } if ( testDTO.getDisable() != null ) { test.setDisable( testDTO.getDisable() ); } if ( testDTO.getPrePrice() != null ) { test.setPrePrice( testDTO.getPrePrice().floatValue() ); } try { if ( testDTO.getOneString() != null ) { test.setOneString( byteString.toString( testDTO.getOneString() ) ); } } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } if ( testDTO.getOneInt() != null ) { test.setOneInt( testDTO.getOneInt() ); } if ( testDTO.getItemList() != null ) { for ( ItemDTO itemList : testDTO.getItemList() ) { test.addItem( itemDTOToItem( itemList ) ); } } if ( test.getKv() != null ) { Map<String, String> map = testDTO.getKv(); if ( map != null ) { test.getKv().putAll( map ); } } try { if ( testDTO.getNumberList() != null ) { for ( String numberList : testDTO.getNumberList() ) { test.addNumber( byteString.toString( numberList ) ); } } } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } if ( testDTO.getTypesList() != null ) { for ( TypeEnum typesList : testDTO.getTypesList() ) { test.addTypes( typeEnumToDownloadResourceEnum( typesList ) ); } } if ( test.getNosList() != null ) { List<Integer> list = testDTO.getNosList(); if ( list != null ) { test.getNosList().addAll( list ); } } return test.build(); } @Override public TestDTO toDTO(Test test) { if ( test == null ) { return null; } TestDTO testDTO = new TestDTO(); if ( test.hasId() ) { testDTO.setId( test.getId() ); } try { if ( test.hasName() ) { testDTO.setName( byteString.toString( test.getName() ) ); } } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } try { if ( test.hasCreateTime() ) { testDTO.setCreateTime( new SimpleDateFormat().parse( test.getCreateTime() ) ); } } catch ( ParseException e ) { throw new RuntimeException( e ); } if ( test.hasDownloadResourceTypeEnum() ) { testDTO.setDownloadResourceTypeEnum( downloadResourceEnumToTypeEnum( test.getDownloadResourceTypeEnum() ) ); } if ( test.hasMainItem() ) { testDTO.setMainItem( itemToItemDTO( test.getMainItem() ) ); } if ( test.hasDisable() ) { testDTO.setDisable( test.getDisable() ); } if ( test.hasPrePrice() ) { testDTO.setPrePrice( BigDecimal.valueOf( test.getPrePrice() ) ); } Map<String, String> map = test.getKv(); if ( map != null ) { testDTO.setKv( new HashMap<String, String>( map ) ); } try { if ( test.hasOneString() ) { testDTO.setOneString( byteString.toString( test.getOneString() ) ); } } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } if ( test.hasOneInt() ) { testDTO.setOneInt( test.getOneInt() ); } List<ItemDTO> list = itemListToItemDTOList( test.getItemList() ); if ( list != null ) { testDTO.setItemList( list ); } ProtocolStringList protocolStringList = test.getNumberList(); if ( protocolStringList != null ) { testDTO.setNumberList( new ArrayList<String>( protocolStringList ) ); } List<TypeEnum> list1 = downloadResourceEnumListToTypeEnumList( test.getTypesList() ); if ( list1 != null ) { testDTO.setTypesList( list1 ); } List<Integer> list2 = test.getNosList(); if ( list2 != null ) { testDTO.setNosList( new ArrayList<Integer>( list2 ) ); } return testDTO; } protected DownloadResourceEnum typeEnumToDownloadResourceEnum(TypeEnum typeEnum) { if ( typeEnum == null ) { return null; } DownloadResourceEnum downloadResourceEnum; switch ( typeEnum ) { case download_resource_type_enum_audio: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_audio; break; case download_resource_type_enum_vedio: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_vedio; break; case download_resource_type_enum_picture: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_picture; break; case download_resource_type_enum_txtfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_txtfile; break; case download_resource_type_enum_wordfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_wordfile; break; case download_resource_type_enum_excelfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_excelfile; break; case download_resource_type_enum_pptfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_pptfile; break; case download_resource_type_enum_pdffile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_pdffile; break; default: throw new IllegalArgumentException( "Unexpected enum constant: " + typeEnum ); } return downloadResourceEnum; } protected Item itemDTOToItem(ItemDTO itemDTO) { if ( itemDTO == null ) { return null; } com.ljc.orika.proto.Item.Builder item = Item.newBuilder(); if ( itemDTO.getItemId() != null ) { item.setItemId( itemDTO.getItemId() ); } if ( itemDTO.getPrice() != null ) { item.setPrice( itemDTO.getPrice() ); } if ( itemDTO.getUint32Count() != null ) { item.setUint32Count( itemDTO.getUint32Count() ); } if ( itemDTO.getUint64Count() != null ) { item.setUint64Count( itemDTO.getUint64Count() ); } if ( itemDTO.getSint32Count() != null ) { item.setSint32Count( itemDTO.getSint32Count() ); } if ( itemDTO.getSint64Count() != null ) { item.setSint64Count( itemDTO.getSint64Count() ); } if ( itemDTO.getFixed32Count() != null ) { item.setFixed32Count( itemDTO.getFixed32Count() ); } if ( itemDTO.getFixed64Count() != null ) { item.setFixed64Count( itemDTO.getFixed64Count() ); } if ( itemDTO.getSfixed32Count() != null ) { item.setSfixed32Count( itemDTO.getSfixed32Count() ); } if ( itemDTO.getSfixed64Count() != null ) { item.setSfixed64Count( itemDTO.getSfixed64Count() ); } if ( itemDTO.getType() != null ) { item.setType( ByteString.copyFrom( itemDTO.getType() ) ); } return item.build(); } protected TypeEnum downloadResourceEnumToTypeEnum(DownloadResourceEnum downloadResourceEnum) { if ( downloadResourceEnum == null ) { return null; } TypeEnum typeEnum; switch ( downloadResourceEnum ) { case download_resource_type_enum_audio: typeEnum = TypeEnum.download_resource_type_enum_audio; break; case download_resource_type_enum_vedio: typeEnum = TypeEnum.download_resource_type_enum_vedio; break; case download_resource_type_enum_picture: typeEnum = TypeEnum.download_resource_type_enum_picture; break; case download_resource_type_enum_txtfile: typeEnum = TypeEnum.download_resource_type_enum_txtfile; break; case download_resource_type_enum_wordfile: typeEnum = TypeEnum.download_resource_type_enum_wordfile; break; case download_resource_type_enum_excelfile: typeEnum = TypeEnum.download_resource_type_enum_excelfile; break; case download_resource_type_enum_pptfile: typeEnum = TypeEnum.download_resource_type_enum_pptfile; break; case download_resource_type_enum_pdffile: typeEnum = TypeEnum.download_resource_type_enum_pdffile; break; default: throw new IllegalArgumentException( "Unexpected enum constant: " + downloadResourceEnum ); } return typeEnum; } protected ItemDTO itemToItemDTO(Item item) { if ( item == null ) { return null; } ItemDTO itemDTO = new ItemDTO(); if ( item.hasItemId() ) { itemDTO.setItemId( item.getItemId() ); } if ( item.hasPrice() ) { itemDTO.setPrice( item.getPrice() ); } if ( item.hasUint32Count() ) { itemDTO.setUint32Count( item.getUint32Count() ); } if ( item.hasUint64Count() ) { itemDTO.setUint64Count( item.getUint64Count() ); } if ( item.hasSint32Count() ) { itemDTO.setSint32Count( item.getSint32Count() ); } if ( item.hasSint64Count() ) { itemDTO.setSint64Count( item.getSint64Count() ); } if ( item.hasFixed32Count() ) { itemDTO.setFixed32Count( item.getFixed32Count() ); } if ( item.hasFixed64Count() ) { itemDTO.setFixed64Count( item.getFixed64Count() ); } if ( item.hasSfixed32Count() ) { itemDTO.setSfixed32Count( item.getSfixed32Count() ); } if ( item.hasSfixed64Count() ) { itemDTO.setSfixed64Count( item.getSfixed64Count() ); } if ( item.hasType() ) { itemDTO.setType( BaseMapper.toByte( item.getType() ) ); } return itemDTO; } protected List<ItemDTO> itemListToItemDTOList(List<Item> list) { if ( list == null ) { return null; } List<ItemDTO> list1 = new ArrayList<ItemDTO>( list.size() ); for ( Item item : list ) { list1.add( itemToItemDTO( item ) ); } return list1; } protected List<TypeEnum> downloadResourceEnumListToTypeEnumList(List<DownloadResourceEnum> list) { if ( list == null ) { return null; } List<TypeEnum> list1 = new ArrayList<TypeEnum>( list.size() ); for ( DownloadResourceEnum downloadResourceEnum : list ) { list1.add( downloadResourceEnumToTypeEnum( downloadResourceEnum ) ); } return list1; } }
proto->bean:
看一下protoc生成的java類中的repeated型別的欄位。
get集合的方法後面加上了“List”,就如第4.5章所介紹的,所以強烈建議javabean對應的List<T>型別的欄位名同名且後面加上“List”。
因為optional型別的欄位不能設為null,也推薦nullValueCheckStrategy設為NullValueCheckStrategy.ALWAYS;還可以發現生成的proto對映bean的方法中,會自動呼叫hasXXX方法判斷"null"。
若有bytes型別的欄位,要轉成byte[],要匯入ByteString.class。
當使用的是預設的集合對映策略,若有要轉成List<String>,要手動建立一個工廠方法,正如BaseMapper#createProtocolStringList,因為自動對映生成的方法時會newProtocolStringList(),然而ProtocolStringList是抽象類。
getNumberList返回的型別是ProtocolStringList。
若使用的是CollectionMappingStrategy.ADDER_PREFERRED,因為會一個個add進去,所以無需再呼叫工廠方法;但又因為可能匹配到多個add方法,所以最終還是會使用get-addAll的策略。
bean->proto:
注意byte[]轉bytes時,要手動指定一個對映方法,正如BaseMapper#toByte方法。
不能更新protobuf物件,更新總是會clear-get-addAll:
使用protobuf的builder物件操作時,其中一個原因List<Long>型別的實現是一個UnmodifiableRandomAccessList,mapstruct在更新list時會clear集合,使用會拋異常。
使用protobuf物件而非builder時,集合是一個EmptyList,增刪改查也會拋異常。
使用預設的集合對映策略的結果
@Component
public class TestMapperImpl implements TestMapper {
@Autowired
private ByteString byteString;
@Autowired
private BaseMapper baseMapper;
@Override
public Test toProto(TestDTO testDTO) {
if ( testDTO == null ) {
return null;
}
Builder test = Test.newBuilder();
if ( testDTO.getId() != null ) {
test.setId( testDTO.getId() );
}
try {
if ( testDTO.getName() != null ) {
test.setName( byteString.toString( testDTO.getName() ) );
}
}
catch ( UnsupportedEncodingException e ) {
throw new RuntimeException( e );
}
if ( testDTO.getCreateTime() != null ) {
test.setCreateTime( new SimpleDateFormat().format( testDTO.getCreateTime() ) );
}
if ( testDTO.getDownloadResourceTypeEnum() != null ) {
test.setDownloadResourceTypeEnum( typeEnumToDownloadResourceEnum( testDTO.getDownloadResourceTypeEnum() ) );
}
if ( testDTO.getMainItem() != null ) {
test.setMainItem( itemDTOToItem( testDTO.getMainItem() ) );
}
if ( testDTO.getDisable() != null ) {
test.setDisable( testDTO.getDisable() );
}
if ( testDTO.getPrePrice() != null ) {
test.setPrePrice( testDTO.getPrePrice().floatValue() );
}
try {
if ( testDTO.getOneString() != null ) {
test.setOneString( byteString.toString( testDTO.getOneString() ) );
}
}
catch ( UnsupportedEncodingException e ) {
throw new RuntimeException( e );
}
if ( testDTO.getOneInt() != null ) {
test.setOneInt( testDTO.getOneInt() );
}
if ( test.getItemList() != null ) {
List<Item> list = itemDTOListToItemList( testDTO.getItemList() );
if ( list != null ) {
test.getItemList().addAll( list );
}
}
if ( test.getKv() != null ) {
Map<String, String> map = testDTO.getKv();
if ( map != null ) {
test.getKv().putAll( map );
}
}
if ( test.getNumberList() != null ) {
try {
ProtocolStringList protocolStringList = stringListToProtocolStringList( testDTO.getNumberList() );
if ( protocolStringList != null ) {
test.getNumberList().addAll( protocolStringList );
}
}
catch ( UnsupportedEncodingException e ) {
throw new RuntimeException( e );
}
}
if ( test.getTypesList() != null ) {
List<DownloadResourceEnum> list1 = typeEnumListToDownloadResourceEnumList( testDTO.getTypesList() );
if ( list1 != null ) {
test.getTypesList().addAll( list1 );
}
}
if ( test.getNosList() != null ) {
List<Integer> list2 = testDTO.getNosList();
if ( list2 != null ) {
test.getNosList().addAll( list2 );
}
}
return test.build();
}
protected DownloadResourceEnum typeEnumToDownloadResourceEnum(TypeEnum typeEnum) {
if ( typeEnum == null ) {
return null;
}
DownloadResourceEnum downloadResourceEnum;
switch ( typeEnum ) {
case download_resource_type_enum_audio: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_audio;
break;
case download_resource_type_enum_vedio: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_vedio;
break;
case download_resource_type_enum_picture: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_picture;
break;
case download_resource_type_enum_txtfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_txtfile;
break;
case download_resource_type_enum_wordfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_wordfile;
break;
case download_resource_type_enum_excelfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_excelfile;
break;
case download_resource_type_enum_pptfile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_pptfile;
break;
case download_resource_type_enum_pdffile: downloadResourceEnum = DownloadResourceEnum.download_resource_type_enum_pdffile;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + typeEnum );
}
return downloadResourceEnum;
}
protected Item itemDTOToItem(ItemDTO itemDTO) {
if ( itemDTO == null ) {
return null;
}
com.ljc.orika.proto.Item.Builder item = Item.newBuilder();
if ( itemDTO.getItemId() != null ) {
item.setItemId( itemDTO.getItemId() );
}
if ( itemDTO.getPrice() != null ) {
item.setPrice( itemDTO.getPrice() );
}
if ( itemDTO.getUint32Count() != null ) {
item.setUint32Count( itemDTO.getUint32Count() );
}
if ( itemDTO.getUint64Count() != null ) {
item.setUint64Count( itemDTO.getUint64Count() );
}
if ( itemDTO.getSint32Count() != null ) {
item.setSint32Count( itemDTO.getSint32Count() );
}
if ( itemDTO.getSint64Count() != null ) {
item.setSint64Count( itemDTO.getSint64Count() );
}
if ( itemDTO.getFixed32Count() != null ) {
item.setFixed32Count( itemDTO.getFixed32Count() );
}
if ( itemDTO.getFixed64Count() != null ) {
item.setFixed64Count( itemDTO.getFixed64Count() );
}
if ( itemDTO.getSfixed32Count() != null ) {
item.setSfixed32Count( itemDTO.getSfixed32Count() );
}
if ( itemDTO.getSfixed64Count() != null ) {
item.setSfixed64Count( itemDTO.getSfixed64Count() );
}
if ( itemDTO.getType() != null ) {
item.setType( ByteString.copyFrom( itemDTO.getType() ) );
}
return item.build();
}
protected List<Item> itemDTOListToItemList(List<ItemDTO> list) {
if ( list == null ) {
return null;
}
List<Item> list1 = new ArrayList<Item>( list.size() );
for ( ItemDTO itemDTO : list ) {
list1.add( itemDTOToItem( itemDTO ) );
}
return list1;
}
protected ProtocolStringList stringListToProtocolStringList(List<String> list) throws UnsupportedEncodingException {
if ( list == null ) {
return null;
}
ProtocolStringList protocolStringList = baseMapper.createProtocolStringList( list );
for ( String string : list ) {
protocolStringList.add( byteString.toString( string ) );
}
return protocolStringList;
}
protected List<DownloadResourceEnum> typeEnumListToDownloadResourceEnumList(List<TypeEnum> list) {
if ( list == null ) {
return null;
}
List<DownloadResourceEnum> list1 = new ArrayList<DownloadResourceEnum>( list.size() );
for ( TypeEnum typeEnum : list ) {
list1.add( typeEnumToDownloadResourceEnum( typeEnum ) );
}
return list1;
}
}
11.2、protobuf3
protobuf3和protobuf2基本相同,區別在於生成的列舉物件會多一個UNRECOGNIZED。
所以在對映設,注意設此列舉對映為null。
@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
TypeEnum toTypeEnum(DownloadResourceTypeEnum downloadResourceTypeEnum);
帶有Any型別的對映
@EqualsAndHashCode(callSuper = true)
@Data
public class Test3DTO extends TestDTO {
private ItemDTO details;
}
message Test3 {
int32 id = 1;
string name = 2;
string create_time = 3;
repeated Item3 item = 4;
DownloadResourceTypeEnum download_resource_type_enum = 5;
Item3 main_item = 6;
bool disable = 7;
float pre_price = 8;
map<string, string> kv = 9;
oneof test_oneof {
string one_string = 10;
int32 one_int = 11;
}
repeated string number = 12;
repeated DownloadResourceTypeEnum types = 13;
repeated int32 nos = 14;
google.protobuf.Any details = 15;
}
message Item3 {
int64 item_id = 1;
double price = 2;
uint32 uint32_count = 3; // 對應java int
uint64 uint64_count = 4; // 對應java Long
sint32 sint32_count = 5; // 對應java INT 比常規int32更有效地編碼負數
sint64 sint64_count = 6; // 對應java long 比常規int64更有效地編碼負數
fixed32 fixed32_count = 7; // 對應java int 總是四個位元組。如果值通常大於228,則比uint32更有效
fixed64 fixed64_count = 8; // 對應java Long 總是八個位元組。如果值通常大於256,則比uint64更有效
sfixed32 sfixed32_count = 9; // 對應java INT 總是四個位元組。
sfixed64 sfixed64_count = 10; // 對應java long 總是八個位元組。
bytes type = 11; // 不可變的位元組陣列 不涉及轉碼 通常用於傳輸字元流
}
enum DownloadResourceTypeEnum{
download_resource_type_enum_audio = 0; //音訊
download_resource_type_enum_vedio = 1; //視訊
download_resource_type_enum_picture = 2; //圖片
download_resource_type_enum_txtfile = 3; //txt檔案
download_resource_type_enum_wordfile = 4; //word文件
download_resource_type_enum_excelfile = 5; //excel文件
download_resource_type_enum_pptfile = 6; //ppt文件
download_resource_type_enum_pdffile = 7; //pdf文件
}
@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);
}
@Component
public class TestMapperImpl implements TestMapper {
@Override
public Test3 toProto(Test3DTO test3DTO) {
if ( test3DTO == null ) {
return null;
}
Builder test3 = Test3.newBuilder();
if ( test3DTO.getId() != null ) {
test3.setId( test3DTO.getId() );
}
if ( test3DTO.getName() != null ) {
test3.setName( test3DTO.getName() );
}
if ( test3DTO.getCreateTime() != null ) {
test3.setCreateTime( new SimpleDateFormat().format( test3DTO.getCreateTime() ) );
}
if ( test3DTO.getDownloadResourceTypeEnum() != null ) {
test3.setDownloadResourceTypeEnum( typeEnumToDownloadResourceTypeEnum( test3DTO.getDownloadResourceTypeEnum() ) );
}
if ( test3DTO.getMainItem() != null ) {
test3.setMainItem( toProtoItem( test3DTO.getMainItem() ) );
}
if ( test3DTO.getDisable() != null ) {
test3.setDisable( test3DTO.getDisable() );
}
if ( test3DTO.getPrePrice() != null ) {
test3.setPrePrice( test3DTO.getPrePrice().floatValue() );
}
if ( test3DTO.getOneString() != null ) {
test3.setOneString( test3DTO.getOneString() );
}
if ( test3DTO.getOneInt() != null ) {
test3.setOneInt( test3DTO.getOneInt() );
}
if ( test3DTO.getDetails() != null ) {
test3.setDetails( BaseMapper.packGeneratedMessageV3( toProtoItem( test3DTO.getDetails() ) ) );
}
if ( test3DTO.getItemList() != null ) {
for ( ItemDTO itemList : test3DTO.getItemList() ) {
test3.addItem( toProtoItem( itemList ) );
}
}
if ( test3.getKv() != null ) {
Map<String, String> map = test3DTO.getKv();
if ( map != null ) {
test3.getKv().putAll( map );
}
}
if ( test3DTO.getNumberList() != null ) {
for ( String numberList : test3DTO.getNumberList() ) {
test3.addNumber( numberList );
}
}
if ( test3DTO.getTypesList() != null ) {
for ( TypeEnum typesList : test3DTO.getTypesList() ) {
test3.addTypes( typeEnumToDownloadResourceTypeEnum( typesList ) );
}
}
if ( test3.getNosList() != null ) {
List<Integer> list = test3DTO.getNosList();
if ( list != null ) {
test3.getNosList().addAll( list );
}
}
return test3.build();
}
@Override
public Item3 toProtoItem(ItemDTO itemDTO) {
if ( itemDTO == null ) {
return null;
}
com.ljc.orika.proto3.Item3.Builder item3 = Item3.newBuilder();
if ( itemDTO.getItemId() != null ) {
item3.setItemId( itemDTO.getItemId() );
}
if ( itemDTO.getPrice() != null ) {
item3.setPrice( itemDTO.getPrice() );
}
if ( itemDTO.getUint32Count() != null ) {
item3.setUint32Count( itemDTO.getUint32Count() );
}
if ( itemDTO.getUint64Count() != null ) {
item3.setUint64Count( itemDTO.getUint64Count() );
}
if ( itemDTO.getSint32Count() != null ) {
item3.setSint32Count( itemDTO.getSint32Count() );
}
if ( itemDTO.getSint64Count() != null ) {
item3.setSint64Count( itemDTO.getSint64Count() );
}
if ( itemDTO.getFixed32Count() != null ) {
item3.setFixed32Count( itemDTO.getFixed32Count() );
}
if ( itemDTO.getFixed64Count() != null ) {
item3.setFixed64Count( itemDTO.getFixed64Count() );
}
if ( itemDTO.getSfixed32Count() != null ) {
item3.setSfixed32Count( itemDTO.getSfixed32Count() );
}
if ( itemDTO.getSfixed64Count() != null ) {
item3.setSfixed64Count( itemDTO.getSfixed64Count() );
}
if ( itemDTO.getType() != null ) {
item3.setType( BaseMapper.copyFrom( itemDTO.getType() ) );
}
return item3.build();
}
@Override
public Test3DTO toDTO(Test3 test) {
if ( test == null ) {
return null;
}
Test3DTO test3DTO = new Test3DTO();
test3DTO.setId( test.getId() );
if ( test.getName() != null ) {
test3DTO.setName( test.getName() );
}
testDTO.setCreateTime( BaseMapper.toDateFromString(test.getCreateTime(), "yyyy-mm-dd") );
if ( test.getDownloadResourceTypeEnum() != null ) {
test3DTO.setDownloadResourceTypeEnum( toTypeEnum( test.getDownloadResourceTypeEnum() ) );
}
if ( test.hasMainItem() ) {
test3DTO.setMainItem( toItemDTO( test.getMainItem() ) );
}
test3DTO.setDisable( test.getDisable() );
test3DTO.setPrePrice( BigDecimal.valueOf( test.getPrePrice() ) );
Map<String, String> map = test.getKv();
if ( map != null ) {
test3DTO.setKv( new HashMap<String, String>( map ) );
}
if ( test.getOneString() != null ) {
test3DTO.setOneString( test.getOneString() );
}
test3DTO.setOneInt( test.getOneInt() );
List<ItemDTO> list = item3ListToItemDTOList( test.getItemList() );
if ( list != null ) {
test3DTO.setItemList( list );
}
ProtocolStringList protocolStringList = test.getNumberList();
if ( protocolStringList != null ) {
test3DTO.setNumberList( new ArrayList<String>( protocolStringList ) );
}
List<TypeEnum> list1 = downloadResourceTypeEnumListToTypeEnumList( test.getTypesList() );
if ( list1 != null ) {
test3DTO.setTypesList( list1 );
}
List<Integer> list2 = test.getNosList();
if ( list2 != null ) {
test3DTO.setNosList( new ArrayList<Integer>( list2 ) );
}
if ( test.hasDetails() ) {
test3DTO.setDetails( toItemDTO( BaseMapper.unpack( test.getDetails(), Item3.class ) ) );
}
return test3DTO;
}
@Override
public ItemDTO toItemDTO(Item3 item3) {
if ( item3 == null ) {
return null;
}
ItemDTO itemDTO = new ItemDTO();
itemDTO.setItemId( item3.getItemId() );
itemDTO.setPrice( item3.getPrice() );
itemDTO.setUint32Count( item3.getUint32Count() );
itemDTO.setUint64Count( item3.getUint64Count() );
itemDTO.setSint32Count( item3.getSint32Count() );
itemDTO.setSint64Count( item3.getSint64Count() );
itemDTO.setFixed32Count( item3.getFixed32Count() );
itemDTO.setFixed64Count( item3.getFixed64Count() );
itemDTO.setSfixed32Count( item3.getSfixed32Count() );
itemDTO.setSfixed64Count( item3.getSfixed64Count() );
if ( item3.getType() != null ) {
itemDTO.setType( BaseMapper.toByte( item3.getType() ) );
}
return itemDTO;
}
@Override
public TypeEnum toTypeEnum(DownloadResourceTypeEnum downloadResourceTypeEnum) {
if ( downloadResourceTypeEnum == null ) {
return null;
}
TypeEnum typeEnum;
switch ( downloadResourceTypeEnum ) {
case UNRECOGNIZED: typeEnum = null;
break;
case download_resource_type_enum_audio: typeEnum = TypeEnum.download_resource_type_enum_audio;
break;
case download_resource_type_enum_vedio: typeEnum = TypeEnum.download_resource_type_enum_vedio;
break;
case download_resource_type_enum_picture: typeEnum = TypeEnum.download_resource_type_enum_picture;
break;
case download_resource_type_enum_txtfile: typeEnum = TypeEnum.download_resource_type_enum_txtfile;
break;
case download_resource_type_enum_wordfile: typeEnum = TypeEnum.download_resource_type_enum_wordfile;
break;
case download_resource_type_enum_excelfile: typeEnum = TypeEnum.download_resource_type_enum_excelfile;
break;
case download_resource_type_enum_pptfile: typeEnum = TypeEnum.download_resource_type_enum_pptfile;
break;
case download_resource_type_enum_pdffile: typeEnum = TypeEnum.download_resource_type_enum_pdffile;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + downloadResourceTypeEnum );
}
return typeEnum;
}
protected DownloadResourceTypeEnum typeEnumToDownloadResourceTypeEnum(TypeEnum typeEnum) {
if ( typeEnum == null ) {
return null;
}
DownloadResourceTypeEnum downloadResourceTypeEnum;
switch ( typeEnum ) {
case download_resource_type_enum_audio: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_audio;
break;
case download_resource_type_enum_vedio: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_vedio;
break;
case download_resource_type_enum_picture: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_picture;
break;
case download_resource_type_enum_txtfile: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_txtfile;
break;
case download_resource_type_enum_wordfile: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_wordfile;
break;
case download_resource_type_enum_excelfile: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_excelfile;
break;
case download_resource_type_enum_pptfile: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_pptfile;
break;
case download_resource_type_enum_pdffile: downloadResourceTypeEnum = DownloadResourceTypeEnum.download_resource_type_enum_pdffile;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + typeEnum );
}
return downloadResourceTypeEnum;
}
protected List<ItemDTO> item3ListToItemDTOList(List<Item3> list) {
if ( list == null ) {
return null;
}
List<ItemDTO> list1 = new ArrayList<ItemDTO>( list.size() );
for ( Item3 item3 : list ) {
list1.add( toItemDTO( item3 ) );
}
return list1;
}
protected List<TypeEnum> downloadResourceTypeEnumListToTypeEnumList(List<DownloadResourceTypeEnum> list) {
if ( list == null ) {
return null;
}
List<TypeEnum> list1 = new ArrayList<TypeEnum>( list.size() );
for ( DownloadResourceTypeEnum downloadResourceTypeEnum : list ) {
list1.add( toTypeEnum( downloadResourceTypeEnum ) );
}
return list1;
}
}
test3.setDetails( BaseMapper.packGeneratedMessageV3( toProtoItem( test3DTO.getDetails() ) ) ),這裡涉及了複雜對映,最裡層轉換方法是呼叫了手動定義的方法,因為通過第3.2章可知,自動生成子對映會在複雜轉換規則之後,Any轉javabean中間要先轉成具體的protobuf物件,不先呼叫Any到具體的protobuf物件的轉換,mapstruct會沒有找到相應的轉換髮現,也不會再呼叫BaseMapper#packGeneratedMessageV3,轉而執行規則5,而自動生成一個,但不能滿足具體轉換。
protobuf3中不再有基礎屬性型別的hasXXX檢查,使用string型別預設值是“”,轉換可能會有NPE,比如轉Date,這裡只有手動指定expression轉換testDTO.setCreateTime( BaseMapper.toDateFromString(test.getCreateTime(), "yyyy-mm-dd") );。