• java Bean之间的转换(属性名不同)


    原文文章: https://blog.csdn.net/luliuliu1234/article/details/84141595

    相同属性名时转换:

    import org.springframework.beans.BeanUtils;
    test1 a = new test1();
    test2 b = new test2();
    BeanUtils.copyProperties(a, b);

    封装的Beanutils:

      1 package com.zhiwei.common.utils.bean;
      2 
      3 import java.lang.reflect.Method;
      4 import java.util.ArrayList;
      5 import java.util.List;
      6 import java.util.regex.Matcher;
      7 import java.util.regex.Pattern;
      8 
      9 /**
     10  * Bean 工具类
     11  *
     12  * @author zhiwei
     13  */
     14 public class BeanUtils extends org.springframework.beans.BeanUtils {
     15     /**
     16      * Bean方法名中属性名开始的下标
     17      */
     18     private static final int BEAN_METHOD_PROP_INDEX = 3;
     19 
     20     /**
     21      * 匹配getter方法的正则表达式
     22      */
     23     private static final Pattern GET_PATTERN = Pattern.compile("get(\p{javaUpperCase}\w*)");
     24 
     25     /**
     26      * 匹配setter方法的正则表达式
     27      */
     28     private static final Pattern SET_PATTERN = Pattern.compile("set(\p{javaUpperCase}\w*)");
     29 
     30     /**
     31      * Bean属性复制工具方法。
     32      *
     33      * @param dest 目标对象
     34      * @param src  源对象
     35      */
     36     public static void copyBeanProp(Object dest, Object src) {
     37         try {
     38             copyProperties(src, dest);
     39         } catch (Exception e) {
     40             e.printStackTrace();
     41         }
     42     }
     43 
     44     /**
     45      * 获取对象的setter方法。
     46      *
     47      * @param obj 对象
     48      * @return 对象的setter方法列表
     49      */
     50     public static List<Method> getSetterMethods(Object obj) {
     51         // setter方法列表
     52         List<Method> setterMethods = new ArrayList<Method>();
     53 
     54         // 获取所有方法
     55         Method[] methods = obj.getClass().getMethods();
     56 
     57         // 查找setter方法
     58 
     59         for (Method method : methods) {
     60             Matcher m = SET_PATTERN.matcher(method.getName());
     61             if (m.matches() && (method.getParameterTypes().length == 1)) {
     62                 setterMethods.add(method);
     63             }
     64         }
     65         // 返回setter方法列表
     66         return setterMethods;
     67     }
     68 
     69     /**
     70      * 获取对象的getter方法。
     71      *
     72      * @param obj 对象
     73      * @return 对象的getter方法列表
     74      */
     75 
     76     public static List<Method> getGetterMethods(Object obj) {
     77         // getter方法列表
     78         List<Method> getterMethods = new ArrayList<Method>();
     79         // 获取所有方法
     80         Method[] methods = obj.getClass().getMethods();
     81         // 查找getter方法
     82         for (Method method : methods) {
     83             Matcher m = GET_PATTERN.matcher(method.getName());
     84             if (m.matches() && (method.getParameterTypes().length == 0)) {
     85                 getterMethods.add(method);
     86             }
     87         }
     88         // 返回getter方法列表
     89         return getterMethods;
     90     }
     91 
     92     /**
     93      * 检查Bean方法名中的属性名是否相等。<br>
     94      * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。
     95      *
     96      * @param m1 方法名1
     97      * @param m2 方法名2
     98      * @return 属性名一样返回true,否则返回false
     99      */
    100 
    101     public static boolean isMethodPropEquals(String m1, String m2) {
    102         return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
    103     }
    104 }

    不同属性名时转换:

      两种方式,第一种 使用cglib进行动态生成,缺点:  需要手动维护映射关系。

                        第二种 java8函数式接口,缺点: 不同bean之间进行转换就需要写一个转换方法

      第一种方式

        首先加入依赖:

     1 <dependency>  
     2             <groupId>asm</groupId>  
     3             <artifactId>asm</artifactId>  
     4             <version>3.3.1</version>  
     5         </dependency>  
     6         <dependency>  
     7             <groupId>asm</groupId>  
     8             <artifactId>asm-commons</artifactId>  
     9             <version>3.3.1</version>  
    10         </dependency>  
    11         <dependency>  
    12             <groupId>asm</groupId>  
    13             <artifactId>asm-util</artifactId>  
    14             <version>3.3.1</version>  
    15         </dependency>  
    16         <dependency>  
    17             <groupId>cglib</groupId>  
    18             <artifactId>cglib-nodep</artifactId>  
    19             <version>2.2.2</version>  
    20         </dependency>  

          CglibBean:

     1 package com.zhiwei.common.utils.bean;
     2 
     3 import org.springframework.cglib.beans.BeanGenerator;
     4 import org.springframework.cglib.beans.BeanMap;
     5 
     6 import java.util.Iterator;
     7 import java.util.Map;
     8 import java.util.Set;
     9 
    10 /**
    11  * CglibBean   class
    12  *
    13  * @author zhiwei
    14  * @date 2020/09/28
    15  */
    16 public class CglibBean {
    17     /**
    18      * 实体Object
    19      */
    20     public Object object = null;
    21     /**
    22      * 属性map
    23      */
    24     public BeanMap beanMap = null;
    25 
    26     public CglibBean() {
    27     }
    28 
    29     public CglibBean(Map<String, Class> propertyMap) {
    30         this.object = generateBean(propertyMap);
    31         this.beanMap = BeanMap.create(this.object);
    32     }
    33 
    34     /**
    35      * 给bean属性赋值
    36      *
    37      * @param property
    38      * @param value
    39      */
    40     public void setValue(String property, Object value) {
    41         beanMap.put(property, value);
    42     }
    43 
    44     /**
    45      * 通过属性名得到属性值
    46      *
    47      * @param property
    48      * @return
    49      */
    50     public Object getValue(String property) {
    51         return beanMap.get(property);
    52     }
    53 
    54     /**
    55      * 得到该实体bean对象
    56      *
    57      * @return
    58      */
    59     public Object getObject() {
    60         return this.object;
    61     }
    62 
    63     /**
    64      * 创建cglib动态代理的bean
    65      *
    66      * @param propertyMap 通过map创建
    67      * @return 返回bean对象
    68      */
    69     @SuppressWarnings("rawtypes")
    70     private Object generateBean(Map<String, Class> propertyMap) {
    71         BeanGenerator generator = new BeanGenerator();
    72         Set keySet = propertyMap.keySet();
    73         for (Iterator i = keySet.iterator(); i.hasNext(); ) {
    74             String key = (String) i.next();
    75             generator.addProperty(key, (Class) propertyMap.get(key));
    76         }
    77         return generator.create();
    78     }
    79 }

        CglibBeanUtils:

      1 package com.zhiwei.common.utils.bean;
      2 
      3 import com.fasterxml.jackson.databind.DeserializationFeature;
      4 import com.fasterxml.jackson.databind.JavaType;
      5 import com.fasterxml.jackson.databind.ObjectMapper;
      6 import org.apache.commons.beanutils.PropertyUtils;
      7 
      8 import java.io.IOException;
      9 import java.lang.reflect.Field;
     10 import java.lang.reflect.InvocationTargetException;
     11 import java.util.HashMap;
     12 import java.util.Map;
     13 
     14 /**
     15  * CglibBeanUtils   class
     16  *
     17  * @author zhiwei
     18  * @date 2020/09/28
     19  */
     20 public class CglibBeanUtils {
     21     private static final ObjectMapper mapper = new ObjectMapper();
     22 
     23     static {
     24         mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
     25     }
     26 
     27     /**
     28      * 根据源对象content转换成目标对象,源对象支持集合类型,但源对象中的实体类和目标对象中的实体类需要属性名相同
     29      *
     30      * @param content 源对象
     31      * @param source  需要转换的目标集合类型
     32      * @param param   目标集合类型里封装的实体类
     33      * @return
     34      */
     35     public static <T> T getCollectionBean(Object content, Class<?> collectionClass, Class<?>... elementClasses) {
     36         if (content == null) {
     37             return null;
     38         }
     39         String contentStr = null;
     40         try {
     41             contentStr = mapper.writeValueAsString(content);
     42             JavaType javaType = mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
     43             return mapper.readValue(contentStr, javaType);
     44         } catch (IllegalArgumentException | IOException e) {
     45         }
     46         return null;
     47     }
     48 
     49     /**
     50      * 根据源对象obj转换成目标对象,不支持集合类型,源对象和目标对象属性名需要相同
     51      *
     52      * @param obj源对象
     53      * @param valueType需要转换的目标集合类型
     54      * @return
     55      */
     56     public static <T> T getDataBeanWithType(Object obj, Class<T> valueType) {
     57         String dataNode = null;
     58         try {
     59             dataNode = mapper.writeValueAsString(obj);
     60             return mapper.readValue(dataNode, valueType);
     61         } catch (IOException e) {
     62         }
     63         return null;
     64     }
     65 
     66     /**
     67      * 拷贝bean的不同名称之间属性值,
     68      * 需要手工维护一个bean之间不同属性名的映射关系,不支持源对象或目标对象为集合类型
     69      *
     70      * @param target 目标对象
     71      * @param source 源对象
     72      * @param param  源对象和目标对象的映射关系,其中key为源对象的属性名,value为目标对象的属性名
     73      * @return 目标对象
     74      * @throws ClassNotFoundException
     75      * @throws IllegalArgumentException
     76      * @throws IllegalAccessException
     77      * @throws InvocationTargetException
     78      * @throws NoSuchMethodException
     79      */
     80     @SuppressWarnings("rawtypes")
     81     public static Object getObject(Object target, Object source, Map<String, String> param) throws ClassNotFoundException,
     82             IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
     83         //获取源对象的属性名和值,属性名作为key,值作为value
     84         Map<String, Object> sourceBeanMap = PropertyUtils.describe(source);
     85         // 获取实体对象属性名数组
     86         Field[] fields = source.getClass().getDeclaredFields();
     87         // 属性名,属性类型
     88         Map<String, Class> temp = new HashMap<>();
     89         // 属性名,属性值
     90         Map<String, Object> valueParam = new HashMap<>();
     91         for (Field f : fields) {
     92             // 设置访问权限,否则不能访问私有化属性
     93             f.setAccessible(true);
     94             // 若没有映射关系,则跳过继续寻找有映射关系的属性
     95             if (null == param.get(f.getName()))
     96                 continue;
     97             temp.put(param.get(f.getName()), Class.forName(f.getType().getName()));
     98             for (Map.Entry<String, String> entry : param.entrySet()) {
     99                 if (entry.getKey().equals(f.getName())) {
    100                     Object value = sourceBeanMap.get(entry.getKey());
    101                     valueParam.put(param.get(f.getName()), value);
    102                     break;
    103                 }
    104             }
    105         }
    106         // 根据参数生成CglibBean对象
    107         CglibBean cglibBean = new CglibBean(temp);
    108         for (Map.Entry<String, Object> entry : valueParam.entrySet()) {
    109             cglibBean.setValue(entry.getKey(), entry.getValue());
    110         }
    111         Object object = cglibBean.getObject();
    112         /*// 用object给目标对象赋值
    113         PropertyUtils.copyProperties(target, object);*/
    114         BeanUtils.copyBeanProp(target, object);
    115         return target;
    116     }
    117 
    118     public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException,
    119             IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    120         Map<String, String> mapping = new HashMap<>();
    121         UserDTO source = new UserDTO();
    122         UserVO target = new UserVO();
    123         source.setUserName("expireDate");
    124         source.setUserAge(11);
    125         mapping.put("userName", "name");//source field,target field,
    126         mapping.put("userAge", "age");
    127         target = (UserVO) getObject(target, source, mapping);
    128         System.out.println(target.toString());
    129     }
    130 }

        两个实体类:

     1 @Data
     2 @AllArgsConstructor
     3 @NoArgsConstructor
     4 @Accessors(chain = true)
     5 public class UserDTO {
     6     private String userName;
     7     private Integer userAge;
     8 }
     9 
    10 
    11 @Data
    12 @AllArgsConstructor
    13 @NoArgsConstructor
    14 @Accessors(chain = true)
    15 public class UserVO {
    16     private String name;
    17     private Integer age;
    18 }

      第二种方式

    使用jdk8函数式接口:

     1 public class UserDTO {
     2     private String userName;
     3     private Integer userAge;
     4 
     5     public String getUserName() {
     6         return userName;
     7     }
     8 
     9     public void setUserName(String userName) {
    10         this.userName = userName;
    11     }
    12 
    13     public Integer getUserAge() {
    14         return userAge;
    15     }
    16 
    17     public void setUserAge(Integer userAge) {
    18         this.userAge = userAge;
    19     }
    20 
    21         public UserDTO convert(){
    22         return ((Function<UserDTO,UserVO>) userDto ->{
    23             UserVO userVo = new UserVO();
    24             userVo.setAge(userDto.getUserAge());
    25             userVo.setName(userDto.getUserName());
    26         })
    27     }
    28 }
  • 相关阅读:
    组合索引
    常见的负载均衡策略
    jvm面试都有什么问题?
    Java常见面试题汇总-----------Java基础(NIO与IO的区别)
    关于OOM面试详解
    RabbitMQ几个常用面试题
    消息队列面试题及答案
    什么是B+树
    java并发编程 ||深入理解synchronized,锁的升级机制
    RabbitMQ中交换机的消息分发机制
  • 原文地址:https://www.cnblogs.com/zhiweiXiaomu/p/13743739.html
Copyright © 2020-2023  润新知