通过反射获取字段注解信息,并修改注解信息
需求场景:
最近在做一个excel的导出功能,excel的表头需要合并,合并后的表头是动态的,如下图所示:
解决方案:
1、用EasyExcel 作 excel导出,如下图所示,定义一个excel导出Vo:
@Data
// 头背景设置无填充色
@HeadStyle(fillPatternType = FillPatternType.NO_FILL)
@HeadFontStyle(fontHeightInPoints = 11)
// 内容的背景设无填充色
@ContentStyle(fillPatternType = FillPatternType.NO_FILL,borderLeft= BorderStyle.THIN,borderTop = BorderStyle.THIN,
borderRight = BorderStyle.THIN,borderBottom = BorderStyle.THIN,verticalAlignment = VerticalAlignment.CENTER)
// 内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 12)
public class AllocationProgressDetailOutRes {
@ColumnWidth(20)
@ExcelProperty(value = "数据类别")
@ApiModelProperty(value = "数据类别", example = "非年卡资源包")
private String labelType;
@ColumnWidth(20)
@ExcelProperty(value = "资源类型")
@ApiModelProperty(value = "资源类型", example = "DAC-T")
private String agentOrderType;
@ColumnWidth(20)
@ExcelProperty(value = "资源包名称")
@ApiModelProperty(value = "资源包名称", example = "购买DAC-T计划资源包")
private String agentOrderDesc;
@ColumnWidth(20)
@ExcelProperty(value = {"累计","购买"})
@ApiModelProperty(value = "累计购买", example = "11")
private Long totalPurchase;
@ColumnWidth(20)
@ExcelProperty(value = {"累计","赠送"})
@ApiModelProperty(value = "赠送", example = "11")
private Long totalGive;
@ColumnWidth(20)
@ExcelProperty(value = {"累计","未分配"})
@ApiModelProperty(value = "未分配", example = "11")
private Long totalNotMatch;
@ColumnWidth(20)
@ExcelProperty(value = {"累计","退单"})
@ApiModelProperty(value = "退单", example = "11")
private Long totalBackSvOrder;
@ColumnWidth(20)
@ExcelProperty(value = {"累计","已分配"})
@ApiModelProperty(value = "已分配", example = "11")
private Long totalMatched;
@ColumnWidth(20)
@ExcelProperty(value = {"当前业务月","购买"})
@ApiModelProperty(value = "购买", example = "11")
private Long currentMonthPurchase;
@ColumnWidth(20)
@ExcelProperty(value ={"当前业务月","赠送"})
@ApiModelProperty(value = "赠送", example = "11")
private Long currentMonthGive;
@ColumnWidth(20)
@ExcelProperty(value = {"当前业务月","未分配"})
@ApiModelProperty(value = "未分配", example = "11")
private Long currentMonthNotMatch;
@ColumnWidth(20)
@ExcelProperty(value = {"当前业务月","退单"})
@ApiModelProperty(value = "退单", example = "11")
private Long currentMonthBackSvOrder;
@ColumnWidth(20)
@ExcelProperty(value = {"当前业务月","已分配"})
@ApiModelProperty(value = "已分配", example = "11")
private Long currentMonthMatched;
2、想办法拿到 @ExcelProperty 注解对象,并把value值给修改掉
3、具体代码如下:
Class<AllocationProgressDetailOutRes> clazz = AllocationProgressDetailOutRes.class;
Field[] fields = clazz.getDeclaredFields();
for (AllocationProgressDetailHeadRes headRes : headList) {
String mergeColumn = headRes.getColumnName();
String text = headRes.getText();
for (Field field : fields) {
String fieldName = field.getName();
if (fieldName.startsWith(mergeColumn)) {
ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
//原来的数组
String[] value = annotation.value();
InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
try {
Field annotationField = invocationHandler.getClass().getDeclaredField("memberValues");
annotationField.setAccessible(true);
Map map = (Map) annotationField.get(invocationHandler);
String[] newValue = {text, value[1]};
map.put("value", newValue);
} catch (Exception e) {
log.error("通过反射修改表头内容失败", e);
}
}
}
}
(我这里面的headList 是一个动态的表头集合),通过上述方法后,即可动态修改注解里面的内容,然后也可以实现表头的合并。
----------------------------------手动分割线----------------------------------
下面介绍,如何用反射,比较两个对象里面每个字段的值,并修改对象1的值:
private void compareData(ReportAllocationProgressOverallTableMo currentData,ReportAllocationProgressOverallTableMo lastDayData) {
if (EmptyUtils.isEmpty(lastDayData)) {
//之前的历史数据是空的
return;
}
Class<ReportAllocationProgressOverallTableMo> clazz = ReportAllocationProgressOverallTableMo.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Class<?> type = field.getType();
//这个是判断这个字段类型是否是ReportFieldBean类型
if (type.isAssignableFrom(ReportFieldBean.class)) {
//设置true代表可以访问这个field字段对象
field.setAccessible(true);
try {
Object obj = field.get(currentData);
if (EmptyUtils.isEmpty(obj)) {
continue;
}
ReportFieldBean filedObj = (ReportFieldBean) field.get(currentData);
if (EmptyUtils.isNotEmpty(filedObj) && EmptyUtils.isNotEmpty(filedObj.getFieldValue())) {
Long fieldValue = filedObj.getFieldValue();
int flag = getFlag(fieldValue, lastDayData, field);
//重新设置flag,重新修改currentData对象的值
field.set(currentData, new ReportFieldBean(fieldValue, flag));
}
} catch (Exception e) {
log.error("反射异常", e);
}
}
}
}