Orika是一个简单、快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean,Orika底层采用了javassist类库生成Bean映射的字节码。
官方地址:http://orika-mapper.github.io/orika-docs/
<dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>compile</scope> <version>1.18.16</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.1-jre</version> </dependency>
import lombok.Data; import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class Role { private Integer id; private String name; } import lombok.Data; import lombok.experimental.Accessors; import java.util.List; @Data @Accessors(chain = true) public class User { private String id; private String name; private Integer age; List<User> userList; List<Role> roles; } import lombok.Data; import lombok.experimental.Accessors; import java.util.List; @Data @Accessors(chain = true) public class UserDto { private String id; private String name; private String userName; private Integer age; List<User> userList; List<Role> roleList; }
/** * 基于Orika的属性映射工具类 - Orika是一个简单、快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean,Orika底层采用了javassist类库生成Bean映射的字节码 * <p> * 1. 支持模糊类型映射(如:Integer <-> Long, Integer <-> String) * 2. 支持对象中的list映射 * <p> * 性能:手动拷贝 > cglib beanCopier > orika mapper > spring beanUtils > apache commons beanUtils * */ public class OrikaMapperUtils { /** * 默认字段工厂 */ private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build(); /** * 默认字段实例 */ private static final MapperFacade MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade(); /** * 实例缓存 */ private final static Cache<Object, Object> CACHE_MAPPER_FACADE_MAP = CacheBuilder.newBuilder().maximumSize(100) .concurrencyLevel(10) .expireAfterWrite(60L, TimeUnit.SECONDS) .recordStats() .build(); /** * 映射实体(默认字段) * * @param data 源数据(对象) * @param toClass 映射类对象 * @return 映射类对象 */ public static <E, T> E map(T data, Class<E> toClass) { return MAPPER_FACADE.map(data, toClass); } /** * 映射实体(自定义配置) * * @param data 源数据(对象) * @param toClass 映射类对象 * @param configMap 自定义配置 * - 用于处理源对象与目标对象字段名不匹配的情况 - 格式:{key=源对象中的字段名 : value=目标对象中的字段名} * @return 映射类对象 */ public static <E, T> E map(T data, Class<E> toClass, Map<String, String> configMap) { MapperFacade mapperFacade = getMapperFacade(toClass, data.getClass(), configMap); return mapperFacade.map(data, toClass); } /** * 映射集合(默认字段) * * @param data 源数据(集合) * @param toClass 映射类对象 * @return 映射类对象(集合) */ public static <E, T> List<E> mapAsList(Collection<T> data, Class<E> toClass) { if (Objects.isNull(data)) { return Collections.emptyList(); } else { return MAPPER_FACADE.mapAsList(data, toClass); } } /** * 映射集合(自定义配置) * * @param data 源数据(集合) * @param toClass 映射类 * @param configMap 自定义配置 * - 用于处理源对象与目标对象字段名不匹配的情况 - 格式:{key=源对象中的字段名 : value=目标对象中的字段名} * @return 映射类对象(集合) */ public static <E, T> List<E> mapAsList(Collection<T> data, Class<E> toClass, Map<String, String> configMap) { if (Objects.isNull(data)) { return Collections.emptyList(); } Optional<T> first = data.stream().findFirst(); if (first.isPresent()) { MapperFacade mapperFacade = getMapperFacade(toClass, first.get().getClass(), configMap); return mapperFacade.mapAsList(data, toClass); } else { return Collections.emptyList(); } } /** * 获取自定义映射 * * @param toClass 映射类 * @param dataClass 数据映射类 * @param configMap 自定义配置 * @return 映射类对象 */ private static <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap) { String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName(); Object o = CACHE_MAPPER_FACADE_MAP.getIfPresent(mapKey); MapperFacade mapperFacade; if (Objects.isNull(o)) { MapperFactory factory = new DefaultMapperFactory.Builder().build(); ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass); configMap.forEach(classMapBuilder::field); classMapBuilder.byDefault().register(); mapperFacade = factory.getMapperFacade(); CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade); } else { mapperFacade = (MapperFacade) o; } return mapperFacade; } }
import java.util.*; public class OrikaMapperTest { public static void main(String[] args) { User userA = new User().setId("111").setName("张三").setAge(20); userA.setUserList(Arrays.asList(new User[]{new User().setId("121").setName("张三1").setAge(21), new User().setId("122").setName("张三2").setAge(22)})); userA.setRoles(Arrays.asList(new Role[]{new Role().setId(1).setName("老师"), new Role().setId(2).setName("班主任")})); Map<String, String> map = new HashMap<String, String>() { { put("roles", "roleList"); } }; UserDto userDto = OrikaMapperUtils.map(userA, UserDto.class, map); System.out.println("无configMap的对象映射(源):" + userA); System.out.println("无configMap的对象映射(目标):" + userDto); Map<String, String> configMap = new HashMap<String, String>() { { put("name", "userName"); } }; UserDto userDto2 = OrikaMapperUtils.map(userA, UserDto.class, configMap); System.out.println("带configMap的对象映射(源):" + userA); System.out.println("带configMap的对象映射(目标):" + userDto2); //A对象 List<User> listA = Arrays.asList(new User().setId("123").setName("张三").setAge(20)); List<UserDto> userDtos = OrikaMapperUtils.mapAsList(listA, UserDto.class); System.out.println("无configMap的list映射(源):" + listA); System.out.println("无configMap的list映射(目标):" + userDtos); List<UserDto> userDtos2 = OrikaMapperUtils.mapAsList(listA, UserDto.class, configMap); System.out.println("带configMap的list映射(源):" + listA); System.out.println("带configMap的list映射(目标):" + userDtos2); } }
- 无configMap的对象映射(源):User(id=111, name=张三, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roles=[Role(id=1, name=老师), Role(id=2, name=班主任)])
- 无configMap的对象映射(目标):UserDto(id=111, name=张三, userName=null, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roleList=[Role(id=1, name=老师), Role(id=2, name=班主任)])
- 带configMap的对象映射(源):User(id=111, name=张三, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roles=[Role(id=1, name=老师), Role(id=2, name=班主任)])
- 带configMap的对象映射(目标):UserDto(id=111, name=张三, userName=null, age=20, userList=[User(id=121, name=张三1, age=21, userList=null, roles=null), User(id=122, name=张三2, age=22, userList=null, roles=null)], roleList=[Role(id=1, name=老师), Role(id=2, name=班主任)])
- 无configMap的list映射(源):[User(id=123, name=张三, age=20, userList=null, roles=null)]
- 无configMap的list映射(目标):[UserDto(id=123, name=张三, userName=null, age=20, userList=null, roleList=null)]
- 带configMap的list映射(源):[User(id=123, name=张三, age=20, userList=null, roles=null)]
- 带configMap的list映射(目标):[UserDto(id=123, name=张三, userName=null, age=20, userList=null, roleList=null)]