在java项目中,由于业务场景需要,我们经常会需要做bean的转换。
最基本的写法是get/set去对每个属性赋值,但是,更多的时候,bean里面的属性比较多,如果每次都这么手动写,工作量毕竟大,而且也不易维护。
apache,和spring都有BeanUtils,但是是基于反射的,性能较差。当然也有性能高的,比如BeanCopier,但是只能用于属性名一样的两个bean。有没有性能比较好,适用性也比较好的呢?
orika可以满足。
1.jar包
<dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.5.4</version> </dependency>
2.创建映射工厂
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
3.映射门面
MapperFacade mapperFacade = mapperFactory.getMapperFacade();
4.示例
User
@Data public class User { private Integer id; private String name; }
UserDTO
@Data @ToString(callSuper = true) public class UserInfoDTO extends User { private Integer age; private String nickname; private String sex; }
写一个创建Bean的函数
public User buildUser(){ User user = new User(); user.setId(1); user.setName("Bane"); return user; }
4.1.基础用法
@Test public void simple(){ User user = buildUser(); MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); MapperFacade mapperFacade = mapperFactory.getMapperFacade(); UserInfoDTO userInfoDTO = mapperFacade.map(user, UserInfoDTO.class); out.println(userInfoDTO); }
执行结果:
UserInfoDTO(super=User(id=1, name=Bane), age=null, nickname=null, sex=null)
4.2组合使用
通过源码可见,bean的转换主要通过map方法,但是,map有很多重载,根据参数类型不一样,可以处理不同的场景。
创建一个UserExtend作为User的属性扩展
@Data public class UserExtend { private Integer id; private Integer userId; private Integer age; private String nickname; private Integer sex; }
创建UserExtend的创建函数
public UserExtend buildUserExtend(){ UserExtend userExtend = new UserExtend(); userExtend.setId(2); userExtend.setAge(4); userExtend.setNickname("落雁沙"); userExtend.setSex(1); return userExtend; }
把两个bean赋值给一个bean
@Test public void simple2(){ User user = buildUser(); UserExtend userExtend = buildUserExtend(); MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); MapperFacade mapperFacade = mapperFactory.getMapperFacade(); UserInfoDTO userInfoDTO = mapperFacade.map(user, UserInfoDTO.class); mapperFacade.map(userExtend,userInfoDTO); out.println(userInfoDTO); }
执行结果:
UserInfoDTO(super=User(id=2, name=Bane), age=4, nickname=落雁沙, sex=1)
结果发现id 被覆盖了,这个时候,我们需要在UserExtend和UserInfoDTO做转换的时候,忽略id。
mapperFactory.classMap(UserExtend.class,UserInfoDTO.class).exclude("id").register();
执行结果:
UserInfoDTO(super=User(id=1, name=Bane), age=null, nickname=null, sex=null)
4.3 结果转换
有的时候,我们要对两个bean的属性值,进行转换,这需要我们自己去设置转换函数
@Test public void simple3(){ User user = buildUser(); UserExtend userExtend = buildUserExtend(); MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); mapperFactory.getConverterFactory().registerConverter("sexConverter", new CustomConverter<Integer, String>() { @Override public String convert(Integer source, Type<? extends String> destinationType, MappingContext mappingContext) { String sexStr = ""; switch (source){ case 1: sexStr = "男"; break; case 2: sexStr= "女"; break; default: sexStr = "保密"; break; } return sexStr; } }); mapperFactory.classMap(UserExtend.class,UserInfoDTO.class) .exclude("id") .fieldMap("sex","sex").converter("sexConverter").add() .register(); MapperFacade mapperFacade = mapperFactory.getMapperFacade(); UserInfoDTO userInfoDTO = mapperFacade.map(user, UserInfoDTO.class); mapperFacade.map(userExtend,userInfoDTO); out.println(userInfoDTO); }
执行结果:
UserInfoDTO(super=User(id=1, name=Bane), age=null, nickname=null, sex=男)