Java中ModelMapper 的高級使用
ModelMapper 高級使用
ModelMapper 是一個 Object To Object 的工具,類似於 MapStruct又不同於 MapStruct。主要原因是 ModelMapper 是利用反射的原理實現的 Object To Object。
ModelMapper 官方API : http://modelmapper.org/user-manual/property-mapping/
使用實例
本實例實現瞭條件映射、嵌套映射(對象中有對象映射)、自定義屬性映射、List 集合映射(對象中有集合映射)、Map集合映射(對象中有集合映射)、忽略映射,默認值設置(ModelMapper 的默認值設置時一不小心就會入坑,如果直接設置默認值,當再賦值轉換時,默認值會覆蓋賦值的值,所以設置默認值需要結合條件映射)等。
驗證瞭對象屬性為集合,集合中還有集合能夠使用 ModelMapper 進行轉換。不足點是這個實例中沒有驗證有繼承關系時的映射(使用 modelMapper.includeBase(父類1, 父類2) 方法),多個屬性映射為一個屬性或一個屬性映射為多個屬性(使用 PropertyMap 轉換器)。
- 使用條件映射設置默認值。當 age/createTime 沒有值時設置默認值為18/當前時間,有值時不設置默認值;
- 嵌套映射,自定義屬性映射。Source 的 sourceSon 成員變量 映射到 Destination 的 destinationSon 成員變量;
- List集合映射。Source 的 listSon 成員變量 映射到 Destination 的 sonList 成員變量;
- Map集合映射。Source 的 mapSon 成員變量 映射到 Destination 的 sonMap 成員變量;
- 忽略映射。忽略 Destination 的 excessParam 成員變量,如果不忽略將驗證不過,報 org.modelmapper.MappingException: ModelMapper mapping errors;
實體類
(1)BaseClass
@Getter @Setter public class BaseClass { private String id; private String name; public BaseClass() { } public BaseClass(String id, String name) { this.id = id; this.name = name; } }
(2)SouSubClass
@Getter @Setter public class SouSubClass { private String sonId; private String sonName; private List<BaseClass> grandSons; public SouSubClass() { } public SouSubClass(String sonId, String sonName) { this.sonId = sonId; this.sonName = sonName; } }
(3)DestSubClass
@Getter @Setter public class DestSubClass { private String dsonId; private String sonName; private String excessParam; private List<BaseClass> grandSons; public DestSubClass(){ } public DestSubClass(String dsonId, String sonName) { this.dsonId = dsonId; this.sonName = sonName; } }
(4)Source
@Getter @Setter public class Source { private String id; private String name; private Integer age; private SouSubClass sourceSon; private List<SouSubClass> listSon; private Map<Integer, SouSubClass> mapSon; private Date createTime; public Source() { } public Source(String id, String name) { this.id = id; this.name = name; } public Source(String id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } }
(5)Destination
@Getter @Setter public class Destination { private Long id; private String name; private Integer age; private DestSubClass destinationSon; private List<DestSubClass> sonList; private Map<Integer, DestSubClass> sonMap; private String excessParam; private Date createTime; public Destination() { } public Destination(Long id, String name) { this.id = id; this.name = name; } }
ModelMapper 配置類
/** * 描述:ModelMapper 配置 */ @Configuration public class ModelMapperConfig { @Bean @Scope("singleton") public ModelMapper getModelMapper() { ModelMapper modelMapper = new ModelMapper(); //默認為standard模式,設置為strict模式 modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); // 類型映射代碼 sourceSonToDestinationSon(modelMapper); sourceToDestination(modelMapper); //驗證映射 modelMapper.validate(); // 配置代碼 return modelMapper; } /** * 描述:聲明 Source 類轉 Destination 類的 Mapper * @param modelMapper * @Date 2019/05/09 */ private void sourceSonToDestinationSon(ModelMapper modelMapper) { modelMapper.createTypeMap(SouSubClass.class, DestSubClass.class) .addMapping(SouSubClass::getSonId, DestSubClass::setDsonId) .addMapping(SouSubClass::getSonName, DestSubClass::setSonName) .addMappings(mapper -> mapper.skip(DestSubClass::setExcessParam)); } private void sourceToDestination(ModelMapper modelMapper) { modelMapper.createTypeMap(Source.class, Destination.class) .addMappings(mapper -> mapper.using((Converter<Integer, Integer>) context -> { if (context.getSource() == null) { return 18; } return context.getSource(); }).map(Source::getAge, Destination::setAge)) .addMappings(mapper -> mapper.using((Converter<Date, Date>) context -> { if (context.getSource() == null) { return new Date(); } return context.getSource(); }).map(Source::getCreateTime, Destination::setCreateTime)) .addMapping(Source::getSourceSon, Destination::setDestinationSon) .addMapping(Source::getListSon, Destination::setSonList) .addMapping(Source::getMapSon, Destination::setSonMap) .addMappings(mapper -> mapper.skip(Destination::setExcessParam)); } }
ModelMapper Service 類
public interface TestService { Destination testSourceToDestination(Source source); List<Destination> testSourceToDestinationList(List<Source> sources); }
@Service public class TestServiceImpl implements TestService { @Autowired private ModelMapper modelMapper; @Override public Destination testSourceToDestination(Source source) { Destination destination = modelMapper.map(source, Destination.class); return destination; // a 處 } @Override public List<Destination> testSourceToDestinationList(List<Source> sources) { Type type = new TypeToken<List<Destination>>(){}.getType(); List<Destination> destinations = modelMapper.map(sources, type); return destinations; // b 處 } }
測試類
@RunWith(SpringRunner.class) @SpringBootTest(classes = TestApplication.class) public class TestServiceImplTest { @Autowired private TestService testService; private static Source source1 = new Source("a", "發生的", 24); private static Source source2 = new Source("b", "發生的"); private static List<Source> sources = new ArrayList<>(); static { List<BaseClass> baseClasses1 = new ArrayList<>(); baseClasses1.add(new BaseClass("aa", "發生的111")); baseClasses1.add(new BaseClass("bb", "發生的222")); SouSubClass subClass1 = new SouSubClass("aaa", "發生的3333"); subClass1.setGrandSons(baseClasses1); List<BaseClass> baseClasses2 = new ArrayList<>(); baseClasses2.add(new BaseClass("cc", "國防觀")); baseClasses2.add(new BaseClass("dd", "國防觀")); SouSubClass subClass2 = new SouSubClass("ccc", "規范的大哥"); subClass2.setGrandSons(baseClasses2); List<SouSubClass> sourceSonList = new ArrayList<>(); sourceSonList.add(subClass1); sourceSonList.add(subClass2); Map<Integer, SouSubClass> sourceSonMap = new HashMap<>(); sourceSonMap.put(1, subClass1); sourceSonMap.put(2, subClass2); source1.setCreateTime(new Date(System.currentTimeMillis()-98978609)); source1.setSourceSon(subClass1); source1.setListSon(sourceSonList); source1.setMapSon(sourceSonMap); source2.setSourceSon(subClass1); source2.setListSon(sourceSonList); source2.setMapSon(sourceSonMap); sources.add(source1); sources.add(source2); } @Test public void testSourceToDestination() { testService.testSourceToDestination(source1); testService.testSourceToDestination(source2); } @Test public void testSourceToDestinationList() { testService.testSourceToDestinationList(sources); } }
測試結果
在 ab 兩處打上斷點,查看變量轉換前後的值,證實轉換成功。
到此這篇關於Java中ModelMapper 的高級使用的文章就介紹到這瞭,更多相關Java ModelMapper內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java Spring集成MapStruct詳情
- 使用spring動態獲取接口的不同實現類
- 教你Spring如何使用三級緩存解決循環依賴
- spring boot寫java web和接口
- java中VO和DTO之間的轉換實現