dozer设计通用的自定义转换器

场景

做国土项目的时候遇到了个类似头疼的问题,就是展现数据
由于要计算统计土地的面积,精度要求,所以 pojo 中用的 BigDecimal 类型,但是在展示的时候类似于表格的形式,没有数据默认就是不填,想来想去还是第三种样式比较方便,前端也好处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"applyLandArea": 14.6121,
"xxxLandArea": null,
"xxxLandArea": null
}
{
"applyLandArea": 14.6121,
"xxxLandArea": 0,
"xxxLandArea": 0
}
{
"applyLandArea": 14.6121,
"xxxLandArea": “”,
"xxxLandArea": “”
}

dozer 也是最近接触的,以前老是自己手动转换,当属性的数量多起来,伴随着大量的 set 方法,dozer 解决了这部分问题,当你转换的属性比较多并且类型不等的时候,这个时候就需要自己定义转换器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//类级别
<mappings>
<mapping relationship-type="non-cumulative">
<!-- 省略 -->
</mapping>
</mappings>

//属性级别
<field relationship-type="cumulative">
<a>hintList</a>
<b>hintList</b>
<a-hint>org.dozer.vo.TheFirstSubClass</a-hint>
<b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint>
</field>
核心代码

自定义转换器必须实现 CustomConverter 接口
重写 convert 方法

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
public class LandActualConverter implements CustomConverter {

@Override
public Object convert(Object destination, Object source, Class<?> destinationClass, Class<?> sourceClass) {

// 如果满足条件,进行转换
final String emptyStr = "";
boolean havevalue = source instanceof LandActual && Objects.equals(destinationClass, LandActualVm.class);
if (havevalue) {
destination = new LandActualVm();
Field[] fields = source.getClass().getDeclaredFields();
for (Field field : fields) {
Class<?> type = field.getType();
String fieldName = field.getName();
Object value = BeanConverter.invokeGet(source, fieldName);
String baseValue = value + emptyStr;

// 如果为不为null,全部正常处理
if (value != null) {
if (Objects.equals(type, Short.class)) {
BeanConverter.invokeSet(destination, fieldName, new Short(baseValue));
}
if (Objects.equals(type, String.class)) {
BeanConverter.invokeSet(destination, fieldName, baseValue);
}
if (Objects.equals(type, Date.class)) {
BeanConverter.invokeSet(destination, fieldName, DateUtils.parse(baseValue));
}
if (Objects.equals(type, BigDecimal.class)) {
BeanConverter.invokeSet(destination, fieldName, baseValue);
}
// 如果为null,将空值转变成""
} else {
if (Objects.equals(type, Short.class)) {
}
if (Objects.equals(type, String.class)) {
}
if (Objects.equals(type, Date.class)) {
}
if (Objects.equals(type, BigDecimal.class)) {
BeanConverter.invokeSet(destination, fieldName, emptyStr);
}
}
}
return destination;
} else {
return new LandActualVm();
}

}

反射实现通用性
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
public class BeanConverter {

/**
* java反射bean的get方法
*
* @param objectClass
* @param fieldName
* @return
*/
@SuppressWarnings("unchecked")
public static Method getGetMethod(Class objectClass, String fieldName) {
StringBuffer sb = new StringBuffer();
sb.append("get");
sb.append(fieldName.substring(0, 1).toUpperCase());
sb.append(fieldName.substring(1));
try {
return objectClass.getMethod(sb.toString());
} catch (Exception e) {
}
return null;
}

/**
* java反射bean的set方法
*
* @param objectClass
* @param fieldName
* @return
*/
@SuppressWarnings("unchecked")
public static Method getSetMethod(Class objectClass, String fieldName) {
try {
Class[] parameterTypes = new Class[1];
Field field = objectClass.getDeclaredField(fieldName);
parameterTypes[0] = field.getType();
StringBuffer sb = new StringBuffer();
sb.append("set");
sb.append(fieldName.substring(0, 1).toUpperCase());
sb.append(fieldName.substring(1));
Method method = objectClass.getMethod(sb.toString(), parameterTypes);
return method;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 执行set方法
*
* @param o
* 执行对象
* @param fieldName
* 属性
* @param value
* 值
*/
public static void invokeSet(Object o, String fieldName, Object value) {
Method method = getSetMethod(o.getClass(), fieldName);
try {
method.invoke(o, new Object[] { value });
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 执行get方法
*
* @param o
* 执行对象
* @param fieldName
* 属性
*/
public static Object invokeGet(Object o, String fieldName) {
Method method = getGetMethod(o.getClass(), fieldName);
try {
return method.invoke(o, new Object[0]);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}