常见场景
我们如果有两个具有很多相同属性名的JavaBean对象a和b,想把a中的属性赋值到b,例如
接口中将接收到的前端请求参数XxxReqVo,我们想把这个入参转化为XxxQuery对象作为数据库的查询条件对象
传统做法是手动set,即
1 2 3 4 5
| XxxQuery xxxQuery = new XxxQuery();
xxxQuery .setAxx(xxxReqVo.getAxx()); xxxQuery .setBxx(xxxReqVo.getBxx()); xxxQuery .setCxx(xxxReqVo.getCxx());
|
如果有几十个需要赋值的的字段呢?那就很头疼了org.springframework.beans.BeanUtils,它提供了对java反射和自省API的包装。它里面还有很多工具类,这里我们介绍一下该类下面的copyProperties方法,该工具方法可以帮我们大大简化这一步
1 2 3 4 5 6 7 8 9
| @Data public class User { private String id; private String name; private String age; private String account; private String password; }
|
1 2 3 4 5 6 7 8
| @Data public class Person { private String id; private String name; private String age; private String sex; }
|
测试数据
1 2 3 4 5 6 7 8 9 10 11 12
| public class Test { public static void main(String[] args) { User user = new User(); user.setId("1"); user.setAge("2"); user.setName("wzh"); user.setAccount("wangzh"); user.setPassword("1111"); Person person = new Person(); BeanUtils.copyProperties(user,person); }
|
实验结果
1
| Person(id=1, name=wzh, age=2, sex=null)
|
结论
1
| BeanUtils.copyProperties(source,target);
|
- 源对象source的属性拷贝值赋给目标对象target的过程中,属性名和属性类型都相同的属性才能被成功拷贝赋值,例如id,name,age这三个目标对象的属性被赋值成功,目标对象中的sex属性,由于源对象中没有同名的属性所以没法被赋值成功。
- 做赋值的属性一定要有对应的setter/getter才能成功赋值
利用忽略值进行合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Data public class WxLoginResp {
private String sessionKey;
private String openId;
private String nickname;
private String avatarUrl;
private String gender;
@JsonSerialize(using=ToStringSerializer.class) private Integer isVolunteer;
@JsonSerialize(using= ToStringSerializer.class) private Long userId;
@JsonSerialize(using= ToStringSerializer.class) private Long volunteerId; }
|
wxLoginResp1
1 2 3
| WxLoginResp wxLoginResp1 = new WxLoginResp(); wxLoginResp1.setOpenId("dkhgkdg"); wxLoginResp1.setSessionKey("dkldgaslg");
|
wxLoginResp2
1 2 3 4
| WxLoginResp wxLoginResp2 = new WxLoginResp(); wxLoginResp2.setNickname("dkhgkdg"); wxLoginResp2.setIsVolunteer("dkldgaslg"); ...除wxLoginResp1赋值过的的其他值都赋值
|
接下来如果我将wxLoginResp2的值赋值给wxLoginResp1BeanUtils.copyProperties(wxLoginResp2,wxLoginResp2);
那么wxLoginResp1当中的,openId和SessionKey的值是NULL。
因为在wxLoginResp2当中,openId和SessionKey没有被赋值啊,所以过去肯定是NULL
这个时候,其实我们可以自己新建一个类,这个类只有openId和SessionKey的属性,在将这个类重新转化给wxLoginResp2,但是太冗余了
于是我们引进ignore,赋值时忽略某些属性
1 2 3 4
| String[] ignore = {"sessionKey","openId"}; BeanUtils.copyProperties(wxLoginResp1, wxLoginResp,ignore); log.info("wxLoginResp1_{}",wxLoginResp1); return Result.ok(wxLoginResp);
|
封装了又一个类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
| package com.example.fresh_demo.utils;
import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.converters.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils;
import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;
@Slf4j public class ConverterUtils { private static final Logger LOG = LoggerFactory.getLogger(ConverterUtils.class);
public static <FROM, TO> TO po2dto(FROM po, Class<TO> clazz) { return converte(po, clazz); }
public static <FROM, TO> List<TO> po2dto(List<FROM> poList, Class<TO> clazz) { return converte(poList, clazz); }
public static <FROM, TO> TO dto2po(FROM dto, Class<TO> clazz) { return converte(dto, clazz); }
public static <FROM, TO> List<TO> dto2po(List<FROM> dtoList, Class<TO> clazz) { return converte(dtoList, clazz); }
public static <FROM, TO> TO converte(FROM from, Class<TO> clazz) { TO to = null; if (null != from) { try { to = clazz.newInstance(); org.apache.commons.beanutils.ConvertUtils.register(new DateConverter(null), java.util.Date.class); org.apache.commons.beanutils.ConvertUtils.register(new LongConverter(null), Long.class); org.apache.commons.beanutils.ConvertUtils.register(new ShortConverter(null), Short.class); org.apache.commons.beanutils.ConvertUtils.register(new IntegerConverter(null), Integer.class); org.apache.commons.beanutils.ConvertUtils.register(new DoubleConverter(null), Double.class); org.apache.commons.beanutils.ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class); ConvertUtils.register(new BooleanConverter(null), Boolean.class); BeanUtils.copyProperties(from, to); } catch (IllegalAccessException e) { LOG.error("IllegalAccessException: ", e.getMessage()); } catch (InstantiationException e) { LOG.error("InstantiationException: ", e.getMessage()); } } return to; }
public static <FROM, TO> List<TO> converte(List<FROM> fromList, Class<TO> clazz) { List<TO> toList = new ArrayList<>(); if (null != fromList && !fromList.isEmpty()) { for (FROM from : fromList) { TO to = converte(from, clazz); if (null != to) { toList.add(to); } } } return toList; }
public static List<String> Long2String(List<Long> list) { if (null == list) { return null; } List<String> stringList = new ArrayList<>(); if (!list.isEmpty()) { for (Long l : list) { stringList.add(String.valueOf(l)); } } return stringList; }
}
|
这个可以直接通过类的模版信息去转化
1
| WxLoginResp wxLoginResp1 = ConverterUtils.converte(user, WxLoginResp.class);
|
通过MAP转换为集合
1 2 3 4 5
|
VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(values, new VoucherOrder(), true);
|
两个好办法
1 2 3 4 5
| Map<Long, List<Shop>> map = shopList.stream().collect(Collectors.groupingBy(Shop::getTypeId));
VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(values, new VoucherOrder(), true);
|
将实体类转换成对应的Map
1 2 3 4 5 6 7 8 9 10 11
| UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class); HashMap<String, String > userMap = new HashMap<>(); userMap.put("icon", userDTO.getIcon()); userMap.put("id", String.valueOf(userDTO.getId())); userMap.put("nickName", userDTO.getNickName());
|
- 变量声明:
1
| Map<String, Object> userMap
|
这行代码声明了一个名为userMap
的变量,其类型为Map<String, Object>
。这个Map的键是String类型,值是Object类型。
- BeanUtil.beanToMap()方法:
这个方法的作用是将一个Java Bean转换为一个Map。Java Bean通常是一个遵循特定命名约定的普通Java类,例如属性名遵循驼峰命名法,并提供getter和setter方法。
- 方法参数:
1 2 3
| `userDTO`: 这是要转换的Java Bean对象。 `new HashMap<>()`: 这是一个新的HashMap实例,用于存储转换后的键值对。 `CopyOptions.create()...`: 这是一个链式调用,用于创建并配置`CopyOptions`对象。`CopyOptions`对象用于控制Bean到Map的转换过程。
|
- CopyOptions配置:
1 2 3
| `.setIgnoreNullValue(true)`: 这个设置表示在转换过程中,如果Bean的某个属性值为null,那么这个属性不会被加入到Map中。 `.setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString())`: 这是一个Lambda表达式,用于定义字段值的编辑器。在这个例子中,无论字段的原始值是什么类型,它都会被转换为String类型。这是通过调用`fieldValue.toString()`方法实现的。
|
总结:
这段代码的目的是将一个名为userDTO
的Java Bean对象转换为一个Map,其中:
- 键是Bean的属性名。
- 值是Bean的属性值,如果属性值为null则不会出现在Map中,否则属性值会被转换为String类型。
最后,转换后的Map被赋值给userMap
变量。