java实现具有相同属性名称及相似类型的pojo、dto、vo等的互转

  已应用于实际项目:1.thrift对象与dto之间的互转

                                      2.pojo与dto之间的互转

                                      3.pojo与vo之间的互转

 

1.核心转换工具类,对特别复杂类型不做处理,因为业务场景还未覆盖

package littlehow.convert;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * PojoConvertUtil
 *
 * @author littlehow
 * @time 2017-05-03 16:54
 */
public class PojoConvertUtil {
    private static Logger logger = LoggerFactory.getLogger(PojoConvertUtil.class);
    /**
     * 变量缓存
     */
    private static final Map> cacheFields = new ConcurrentHashMap<>();
    private static final Set basicClass = new HashSet<>();
    static {
        basicClass.add(Integer.class);
        basicClass.add(Character.class);
        basicClass.add(Byte.class);
        basicClass.add(Float.class);
        basicClass.add(Double.class);
        basicClass.add(Boolean.class);
        basicClass.add(Long.class);
        basicClass.add(Short.class);
        basicClass.add(String.class);
        basicClass.add(BigDecimal.class);
    }
    /**
     * 将具有相同属性的类型进行转换
     * @param orig
     * @param 
     * @return
     */
    public static  T convertPojo(Object orig, Class targetClass) {
        try {
            T target = targetClass.newInstance();
            /** 获取源对象的所有变量 */
            Field[] fields = orig.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (isStatic(field)) continue;
                /** 获取目标方法 */
                Field targetField = getTargetField(targetClass, field.getName());
                if (targetField == null) continue;
                Object value = getFiledValue(field, orig);
                if (value == null) continue;
                Class type1 = field.getType();
                Class type2 = targetField.getType();
                //两个类型是否相同
                boolean sameType = type1.equals(type2);
                if (isBasicType(type1)) {
                    if (sameType) setFieldValue(targetField, target, value);
                } else if (value instanceof Map && Map.class.isAssignableFrom(type2)){//对map
                    setMap((Map)value, field, targetField, target);
                } else if (value instanceof Set && Set.class.isAssignableFrom(type2)) {//对set
                    setCollection((Collection)value, field, targetField, target);
                } else if (value instanceof List && List.class.isAssignableFrom(type2)) {//对list
                    setCollection((Collection)value, field, targetField, target);
                } else if (value instanceof Enum && Enum.class.isAssignableFrom(type2)) {//对enum
                    setEnum((Enum)value, field, targetField, target);
                } else if (value instanceof java.util.Date &&
                        java.util.Date.class.isAssignableFrom(type2)) {//对日期类型,不处理如joda包之类的扩展时间,不处理calendar
                    setDate((Date)value, targetField, type2, target, sameType);
                }
            }
            return target;
        } catch (Throwable t) {
            logger.error("转换失败:" + t.getMessage());
            throw new RuntimeException(t.getMessage());
        }
    }

    /**
     * 获取字段值
     * @param field
     * @param obj
     * @return
     */
    private static Object getFiledValue(Field field, Object obj) throws IllegalAccessException {
        //获取原有的访问权限
        boolean access = field.isAccessible();
        try {
            //设置可访问的权限
            field.setAccessible(true);
            return field.get(obj);
        } finally {
            //恢复访问权限
            field.setAccessible(access);
        }
    }

    /**
     * 设置方法值
     * @param field
     * @param obj
     * @param value
     * @throws IllegalAccessException
     */
    private static void setFieldValue(Field field, Object obj, Object value) throws IllegalAccessException {
        //获取原有的访问权限
        boolean access = field.isAccessible();
        try {
            //设置可访问的权限
            field.setAccessible(true);
            field.set(obj, value);
        } finally {
            //恢复访问权限
            field.setAccessible(access);
        }
    }

    /**
     * 转换list
     * @param orig
     * @param targetClass
     * @param 
     * @return
     */
    public static  List convertPojos(List orig, Class targetClass) {
        List list = new ArrayList<>(orig.size());
        for (Object object : orig) {
            list.add(convertPojo(object, targetClass));
        }
        return list;
    }

    /**
     * 设置Map
     * @param value
     * @param origField
     * @param targetField
     * @param targetObject
     * @param 
     */
    private static  void setMap(Map value, Field origField, Field targetField, T targetObject) throws IllegalAccessException, InstantiationException{
        Type origType = origField.getGenericType();
        Type targetType = targetField.getGenericType();
        if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
            ParameterizedType origParameterizedType = (ParameterizedType)origType;
            Type[] origTypes = origParameterizedType.getActualTypeArguments();
            ParameterizedType targetParameterizedType = (ParameterizedType)targetType;
            Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
            if (origTypes != null && origTypes.length == 2 && targetTypes != null && targetTypes.length == 2) {//正常泛型,查看第二个泛型是否不为基本类型
                Class clazz = (Class)origTypes[1];
                if (!isBasicType(clazz) && !clazz.equals(targetTypes[1])) {//如果不是基本类型并且泛型不一致,则需要继续转换
                    Set entries = value.entrySet();
                    Map targetMap = value.getClass().newInstance();
                    for (Map.Entry entry : entries) {
                        targetMap.put(entry.getKey(), convertPojo(entry.getValue(), (Class) targetTypes[1]));
                    }
                    setFieldValue(targetField, targetObject, targetMap);
                    return;
                }
            }
        }
        setFieldValue(targetField, targetObject, value);
    }

    /**
     * 设置集合
     * @param value
     * @param origField
     * @param targetField
     * @param targetObject
     * @param 
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private static  void setCollection(Collection value, Field origField, Field targetField, T targetObject) throws IllegalAccessException, InstantiationException{
        Type origType = origField.getGenericType();
        Type targetType = targetField.getGenericType();
        if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
            ParameterizedType origParameterizedType = (ParameterizedType)origType;
            Type[] origTypes = origParameterizedType.getActualTypeArguments();
            ParameterizedType targetParameterizedType = (ParameterizedType)targetType;
            Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
            if (origTypes != null && origTypes.length == 1 && targetTypes != null && targetTypes.length == 1) {//正常泛型,查看第二个泛型是否不为基本类型
                Class clazz = (Class)origTypes[0];
                if (!isBasicType(clazz) && !clazz.equals(targetTypes[0])) {//如果不是基本类型并且泛型不一致,则需要继续转换
                    Collection collection = value.getClass().newInstance();
                    for (Object obj : value) {
                        collection.add(convertPojo(obj, (Class) targetTypes[0]));
                    }
                    setFieldValue(targetField, targetObject, collection);
                    return;
                }
            }
        }
        setFieldValue(targetField, targetObject, value);
    }

    /**
     * 设置枚举类型
     * @param value
     * @param origField
     * @param targetField
     * @param targetObject
     * @param 
     */
    private static  void setEnum(Enum value, Field origField, Field targetField, T targetObject) throws Exception{
        if (origField.equals(targetField)) {
            setFieldValue(targetField, targetObject, value);
        } else {
            //枚举类型都具有一个static修饰的valueOf方法
            Method method = targetField.getType().getMethod("valueOf", String.class);
            setFieldValue(targetField, targetObject, method.invoke(null, value.toString()));
        }
    }

    /**
     * 设置日期类型
     * @param value
     * @param targetField
     * @param targetFieldType
     * @param targetObject
     * @param 
     */
    private static  void setDate(Date value, Field targetField, Class targetFieldType, T targetObject, boolean sameType) throws IllegalAccessException {
        Date date = null;
        if (sameType) {
            date = value;
        } else if (targetFieldType.equals(java.sql.Date.class)) {
            date = new java.sql.Date(value.getTime());
        } else if (targetFieldType.equals(java.util.Date.class)) {
            date = new Date(value.getTime());
        } else if (targetFieldType.equals(java.sql.Timestamp.class)) {
            date = new java.sql.Timestamp(value.getTime());
        }
        setFieldValue(targetField, targetObject, date);
    }

    /**
     * 获取适配方法
     * @param clazz
     * @param fieldName
     * @return
     */
    public static Field getTargetField(Class clazz, String fieldName) {
        String classKey = clazz.getName();
        Map fieldMap = cacheFields.get(classKey);
        if (fieldMap == null) {
            fieldMap = new HashMap<>();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (isStatic(field)) continue;
                fieldMap.put(field.getName(), field);
            }
            cacheFields.put(classKey, fieldMap);
        }
        return fieldMap.get(fieldName);
    }

    /**
     * 确实是否为基础类型
     * @param clazz
     * @return
     */
    public static boolean isBasicType(Class clazz) {
        return clazz.isPrimitive() || basicClass.contains(clazz);
    }

    /**
     * 判断变量是否有静态修饰符static
     * @param field
     * @return
     */
    public static boolean isStatic(Field field) {
        return (8 & field.getModifiers()) == 8;
    }
}

 

 

 

下面这个类是便于输出展示的,因为只是用于打印,所以不做效率考虑

package littlehow.convert;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * SimpleToStringParent
 *
 * @author littlehow
 * @time 2017-05-04 10:40
 */
public class SimpleToStringParent {

    @Override
    public String toString() {
        try {
            StringBuilder stringBuilder = new StringBuilder("{");
            Field[] fields = this.getClass().getDeclaredFields();
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (Field field : fields) {
                Object value = getFiledValue(field, this);
                if (value == null) continue;
                if (value instanceof Date) {
                    //这里也可以直接转为时间戳
                    value = dateFormat.format((Date)value);
                }
                stringBuilder.append(field.getName()).append("=").append(value).append(",");
            }
            String returnValue = stringBuilder.toString();
            if (returnValue.length() > 1) {
                returnValue = returnValue.substring(0, returnValue.length() - 1);
            }
            return this.getClass().getSimpleName() + returnValue + "}";
        } catch (Exception e) {
            // skip
        }
        return this.getClass().getSimpleName() + "{}";
    }

    /**
     * 获取属性值
     * @param field
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    private Object getFiledValue(Field field, Object obj) throws IllegalAccessException {
        //获取原有的访问权限
        boolean access = field.isAccessible();
        try {
            //设置可访问的权限
            field.setAccessible(true);
            return field.get(obj);
        } finally {
            //恢复访问权限
            field.setAccessible(access);
        }
    }
}

 

 

测试用的4个pojo

1.产品类

package littlehow.convert.pojo;

import littlehow.convert.SimpleToStringParent;

import java.util.List;

/**
 * Product
 *
 * @author littlehow
 * @time 2017-05-04 09:15
 */
public class Product extends SimpleToStringParent {
    private Integer productId;
    private String generalName;
    private String factoryName;
    private String unit;
    private String specification;
    private Integer category;
    private List items;

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public String getGeneralName() {
        return generalName;
    }

    public void setGeneralName(String generalName) {
        this.generalName = generalName;
    }

    public String getFactoryName() {
        return factoryName;
    }

    public void setFactoryName(String factoryName) {
        this.factoryName = factoryName;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public String getSpecification() {
        return specification;
    }

    public void setSpecification(String specification) {
        this.specification = specification;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

    public Integer getCategory() {
        return category;
    }

    public void setCategory(Integer category) {
        this.category = category;
    }
}

 

 

2.商品类

package littlehow.convert.pojo;


import littlehow.convert.SimpleToStringParent;

import java.util.Date;
import java.util.List;

/**
 * Item
 *
 * @author littlehow
 * @time 2017-05-04 09:15
 */
public class Item extends SimpleToStringParent {
    private Long itemId;
    private String itemName;
    private Byte status;
    private Boolean deleted;
    private Date createTime;
    private List skus;

    public Long getItemId() {
        return itemId;
    }

    public void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public Byte getStatus() {
        return status;
    }

    public void setStatus(Byte status) {
        this.status = status;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public List getSkus() {
        return skus;
    }

    public void setSkus(List skus) {
        this.skus = skus;
    }
}

 

 

3.最小库存单位sku

package littlehow.convert.pojo;

import littlehow.convert.SimpleToStringParent;

import java.lang.reflect.Field;

/**
 * Sku
 *
 * @author littlehow
 * @time 2017-05-04 09:15
 */
public class Sku extends SimpleToStringParent {
    private Long skuId;
    private Byte status;
    private Boolean deleted;
    private Double price;
    private Double promoPrice;
    private Integer inventory;
    private Integer minBuy;
    private Integer blockInventory;
    private Color skuColor;

    public Long getSkuId() {
        return skuId;
    }

    public void setSkuId(Long skuId) {
        this.skuId = skuId;
    }

    public Byte getStatus() {
        return status;
    }

    public void setStatus(Byte status) {
        this.status = status;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Double getPromoPrice() {
        return promoPrice;
    }

    public void setPromoPrice(Double promoPrice) {
        this.promoPrice = promoPrice;
    }

    public Integer getInventory() {
        return inventory;
    }

    public void setInventory(Integer inventory) {
        this.inventory = inventory;
    }

    public Integer getMinBuy() {
        return minBuy;
    }

    public void setMinBuy(Integer minBuy) {
        this.minBuy = minBuy;
    }

    public Integer getBlockInventory() {
        return blockInventory;
    }

    public void setBlockInventory(Integer blockInventory) {
        this.blockInventory = blockInventory;
    }

    public Color getSkuColor() {
        return skuColor;
    }

    public void setSkuColor(Color skuColor) {
        this.skuColor = skuColor;
    }
}

 

 

4.属性枚举

package littlehow.convert.pojo;

/**
 * Color
 *
 * @author littlehow
 * @time 2017-05-04 09:21
 */
public enum Color {
    BLACK(1),
    RED(2),
    BLUE(3),
    GREEN(4);
    public final int value;
    Color(int value) {
        this.value = value;
    }

    public static Color valueOf(int value) {
        switch (value) {
            case 1 : return BLACK;
            case 2 : return RED;
            case 3 : return BLUE;
            case 4 : return GREEN;
            default : throw new IllegalArgumentException(value + " is not a enum value");
        }
    }
}

 

 

 

转换用的dto,当然也可以将dto作为转换源

1.产品dto

package littlehow.convert.dto;

import littlehow.convert.SimpleToStringParent;
import littlehow.convert.pojo.Item;

import java.util.List;

/**
 * ProductDto
 *
 * @author littlehow
 * @time 2017-05-04 09:16
 */
public class ProductDto extends SimpleToStringParent {
    private Integer productId;
    private String generalName;
    private String factoryName;
    private String unit;
    private String specification;
    private Integer category;
    private List items;

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public String getGeneralName() {
        return generalName;
    }

    public void setGeneralName(String generalName) {
        this.generalName = generalName;
    }

    public String getFactoryName() {
        return factoryName;
    }

    public void setFactoryName(String factoryName) {
        this.factoryName = factoryName;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public String getSpecification() {
        return specification;
    }

    public void setSpecification(String specification) {
        this.specification = specification;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

    public Integer getCategory() {
        return category;
    }

    public void setCategory(Integer category) {
        this.category = category;
    }
}

 

 

2.商品dto

package littlehow.convert.dto;

import littlehow.convert.SimpleToStringParent;
import littlehow.convert.pojo.Sku;

import java.util.Date;
import java.util.List;

/**
 * ItemDto
 *
 * @author littlehow
 * @time 2017-05-04 09:16
 */
public class ItemDto extends SimpleToStringParent {
    private Integer itemId;
    private String itemName;
    private Byte status;
    private Boolean deleted;
    private Date createTime;
    private List skus;

    public Integer getItemId() {
        return itemId;
    }

    public void setItemId(Integer itemId) {
        this.itemId = itemId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public Byte getStatus() {
        return status;
    }

    public void setStatus(Byte status) {
        this.status = status;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public List getSkus() {
        return skus;
    }

    public void setSkus(List skus) {
        this.skus = skus;
    }
}

 

 

3.skudto

package littlehow.convert.dto;

import littlehow.convert.SimpleToStringParent;
import littlehow.convert.pojo.Color;

/**
 * SkuDto
 *
 * @author littlehow
 * @time 2017-05-04 09:16
 */
public class SkuDto extends SimpleToStringParent {
    private Long skuId;
    private Byte status;
    private Boolean deleted;
    private Double price;
    private Double promoPrice;
    private Integer inventory;
    private Integer minBuy;
    private Integer blockInventory;
    private ColorDto skuColor;

    public Long getSkuId() {
        return skuId;
    }

    public void setSkuId(Long skuId) {
        this.skuId = skuId;
    }

    public Byte getStatus() {
        return status;
    }

    public void setStatus(Byte status) {
        this.status = status;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Double getPromoPrice() {
        return promoPrice;
    }

    public void setPromoPrice(Double promoPrice) {
        this.promoPrice = promoPrice;
    }

    public Integer getInventory() {
        return inventory;
    }

    public void setInventory(Integer inventory) {
        this.inventory = inventory;
    }

    public Integer getMinBuy() {
        return minBuy;
    }

    public void setMinBuy(Integer minBuy) {
        this.minBuy = minBuy;
    }

    public Integer getBlockInventory() {
        return blockInventory;
    }

    public void setBlockInventory(Integer blockInventory) {
        this.blockInventory = blockInventory;
    }

    public ColorDto getSkuColor() {
        return skuColor;
    }

    public void setSkuColor(ColorDto skuColor) {
        this.skuColor = skuColor;
    }
}

 

 

4.颜色属性

package littlehow.convert.dto;

/**
 * ColorDto
 *
 * @author littlehow
 * @time 2017-05-04 09:21
 */
public enum ColorDto {
    BLACK(1),
    RED(2),
    BLUE(3),
    GREEN(4);
    public final int value;
    ColorDto(int value) {
        this.value = value;
    }

    public static ColorDto valueOf(int value) {
        switch (value) {
            case 1 : return BLACK;
            case 2 : return RED;
            case 3 : return BLUE;
            case 4 : return GREEN;
            default : throw new IllegalArgumentException(value + " is not a enum value");
        }
    }
}

 

 

 

测试类,简单的做了一下输出查看

package littlehow.convert.test;

import littlehow.convert.PojoConvertUtil;
import littlehow.convert.dto.ItemDto;
import littlehow.convert.dto.ProductDto;
import littlehow.convert.dto.SkuDto;
import littlehow.convert.pojo.Color;
import littlehow.convert.pojo.Item;
import littlehow.convert.pojo.Product;
import littlehow.convert.pojo.Sku;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * TransTest
 *
 * @author littlehow
 * @time 2017-05-04 10:44
 */
public class TransTest {
    private Product product;

    @Before
    public void init() {
        product = new Product();
        product.setCategory(123);
        product.setFactoryName("littlehow's shop");
        product.setGeneralName("littlehow's product");
        product.setProductId(1);
        product.setSpecification("16*2u");
        product.setUnit("box");
        List items = new ArrayList<>();
        for (int i=1; i<=5; i++) {
            Item item = new Item();
            item.setCreateTime(new Date());
            item.setDeleted(i % 3 == 0);
            item.setItemId((long) i);
            item.setItemName("littlehow's " + i + "th item");
            item.setStatus((byte) (i % 4));
            List skus = new ArrayList<>();
            for (int j=1; j<=i; j++) {
                Sku sku = new Sku();
                sku.setSkuId((long)(j * (i + 5) * 3));
                sku.setStatus((byte) 1);
                sku.setDeleted(false);
                sku.setBlockInventory(5);
                sku.setInventory(j * 100);
                sku.setMinBuy(j * 5);
                sku.setPrice(Double.valueOf(j * 103));
                sku.setPromoPrice(Double.valueOf(j * 101));
                sku.setSkuColor(Color.valueOf(j % 4 + 1));
                skus.add(sku);
            }
            item.setSkus(skus);
            items.add(item);
        }
        product.setItems(items);
    }

    @Test
    public void test() {
        System.out.println(product);//正常输出
        System.out.println("========================");
        ProductDto productDto = PojoConvertUtil.convertPojo(product, ProductDto.class);
        System.out.println(productDto);//正常输出,证明转换正常
        System.out.println("=========================");
        List items = product.getItems();
        List itemDtos = PojoConvertUtil.convertPojos(items, ItemDto.class);
        System.out.println(itemDtos);//正常输出,数组转换成功
    }

    @Test
    public void test1() {
        Sku sku = product.getItems().get(0).getSkus().get(0);
        System.out.println(sku);//正常输出
        System.out.println("=========================");
        SkuDto skuDto = PojoConvertUtil.convertPojo(sku, SkuDto.class);
        System.out.println(skuDto);
    }
}

 

 

能快速完成基础类之间的互转

工作笔记

  littlehow 于2017/5/4

 

你可能感兴趣的:(java)