咱们先来看一张数据扭转的图,这个是DDD思想下各类对象转换的过程。java
VO(View Object):视图对象,用于展现层,它的做用是把某个指定页面(或组件)的全部数据封装起来。git
DTO(Data Transfer Object):数据传输对象,用于展现层与服务层之间的数据传输对象。github
DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。spring
PO(Persistent Object):持久化对象,它跟持久层(一般是关系型数据库)的数据结构造成一一对应的映射关系,若是持久层是关系型数据库,那么,数据表中的每一个字段(或若干个)就对应PO的一个(或若干个)属性。数据库
VO层咱们先不看,从DTO开始,咱们梳理简单一个请求流程中数据会转换几回:segmentfault
咱们先看下操做以前和操做以后的代码,在来详解:数据结构
public static void main(String[] args) { //初始化对象 UserDto userDto = new UserDto(); userDto.setId(1); userDto.setName("java圈"); //////////////////////////// //UserDto转成对象UserDo UserDtoToUserDo userDtoToUserDo = new UserDtoToUserDo(); UserDo userDo = userDtoToUserDo.convert(userDto); //UserDo转成对象UserPo UserDoToUserPo userDoToUserPo = new UserDoToUserPo(); UserPo userPo = userDoToUserPo.convert(userDo); //UserPo转成对象UserDo UserPoToUserDo userPoToUserDo = new UserPoToUserDo(); UserDo userDo1 = userPoToUserDo.convert(userPo); //UserDo转成对象UserDto UserDoToUserDto userDoToUserDto = new UserDoToUserDto(); UserDto userDto1 = userDoToUserDto.convert(userDo1); System.out.println("改造以前的结果:"+userDto1); //////////////////////////// UserDo userDo2 = AssemblerFactory.getInstance().execute(UserDtoToUserDoAssembler.class,userDto, UserDo.class); UserPo userPo1 = AssemblerFactory.getInstance().execute(UserDoToUserPoAssembler.class,userDo2, UserPo.class); UserDo userDo3 = AssemblerFactory.getInstance().execute(UserPoToUserDoAssembler.class,userPo1, UserDo.class); UserDto userDto2 = AssemblerFactory.getInstance().execute(UserDoToUserDtoAssembler.class,userDo3, UserDto.class); System.out.println("改造以后的结果:"+userDto2); }
这段代码用两种方式实现了上述的四个对象的转换:ide
第一种工具
第二种优化
数据转换接口,里面有一个convert转换的方法,须要传入原始对象,和返回对象的类型,直接返回目标对象,便于代码规范化话和代码隔离。
public interface Assembler<R,T> { public T convert(R original,Class<T> targetType); }
AssemblerFactory是一个单例工厂,经过getAssembler传入的类型,获取目标转换对象的实例,ReflectionUtils为Spring-core里面的反射方法;execute执行实现类连的转换方法,须要传入原始对象和目标对象。
public class AssemblerFactory { private static AssemblerFactory INSTANCE = new AssemblerFactory(); private AssemblerFactory(){} public static AssemblerFactory getInstance(){ return INSTANCE; } private Assembler getAssembler(Class type){ Assembler assembler = null; try { assembler = (Assembler) ReflectionUtils.accessibleConstructor(type, new Class[0]).newInstance(new Object[0]); } catch (Throwable e){ e.printStackTrace(); } return assembler; } public <R,T> T execute(Class type,R original,Class<T> targetType){ Assembler assembler = getAssembler(type); T target = (T) assembler.convert(original,targetType); return target; } }
这里提供一个样例实现,实现接口Assembler,添加返回原始对象和目标对象,实现convert业务逻辑转换,这里有可能要问,里面转换的过程是否还能够优化?能够确定是能够的,好比用组合模式,把DTO、VO、PO里面的字段进行封装、用组合+接口的方式实现,可是作起来仍是比较麻烦。这里最好是建议用get/set方法转换,不要用一些序列化工具转换,执行效率没有get/set高。
/** * UserDo 转 UserDto */ public class UserDoToUserDtoAssembler implements Assembler<UserDo,UserDto>{ @Override public UserDto convert(UserDo userDo,Class<UserDto> target){ UserDto userDto = new UserDto(); userDto.setId(userDo.getId()); userDto.setName(userDo.getName()); return userDto; } }
源代码:https://github.com/itrickzhang/spring-demo/tree/master/data-conversion
本文由博客一文多发平台 OpenWrite 发布!