1. 程式人生 > >java實現具有相同屬性名稱及相似型別的pojo、dto、vo等的互轉

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<String, Map<String, Field>> cacheFields = new ConcurrentHashMap<>(); private static final Set<Class> 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 <T> * @return */ public static <T> T convertPojo(Object orig, Class<T> 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 <T> * @return */ public static <T> List<T> convertPojos(List orig, Class<T> targetClass) { List<T> 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 <T> */ private static <T> 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<Map.Entry> 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 <T> * @throws IllegalAccessException * @throws InstantiationException */ private static <T> 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 <T> */ private static <T> 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 <T> */ private static <T> 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<String, Field> 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<Item> 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<Item> getItems() {
        return items;
}

    public void setItems(List<Item> 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<Sku> 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<Sku> getSkus() {
        return skus;
}

    public void setSkus(List<Sku> 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