咱們先來看一張數據扭轉的圖,這個是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 發佈!