- 创建注解以及表头解析工具类
1)HeaderBelongType注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HeaderBelongType {
/**
* 表头所属类型,不传表头默认返回该字段
*
* @return
*/
String[] type() default "";
/**
* 表头所属模型 不传则只根据表头所属类型匹配数据
*
* @return
*/
String[] model() default "";
}
2)创建表头信息实体类
@Data
@ApiModel("表头信息")
public class HeaderInfo {
@ApiModelProperty("表头名称")
private String headerName;
@ApiModelProperty("表头code")
private String headerCode;
}
3)表头解析工具类
@Slf4j
public class HeaderUtil {
private HeaderUtil() {
}
/**
* 获取表头信息
*
* @param headerBelongType 所属表头类型
* @param targetClazz 实体
* @param <T>
* @return 表头信息(表头名称+表头字段名)
*/
public static <T> List<HeaderInfo> getObjectHeader(String headerBelongType, Class<T> targetClazz) {
return getObjectHeader(headerBelongType, null, targetClazz);
}
/**
* 获取表头信息
*
* @param headerBelongType 所属表头类型
* @param targetClazz 实体
* @param model 模型代码,传了就会查找这个模型对应的字段,不传则只查询表头类型对应的字段
* @param <T>
* @return 表头信息(表头名称+表头字段名)
*/
public static <T> List<HeaderInfo> getObjectHeader(String headerBelongType, String model, Class<T> targetClazz) {
List<Field> fieldList = new ArrayList<>();
Class tempClass = targetClazz;
//当父类为null的时候说明到达了最上层的父类(Object类).
while (tempClass != null) {
fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
tempClass = tempClass.getSuperclass();
}
List<HeaderInfo> lists = new ArrayList<>();
HeaderInfo headerInfo = null;
for (Field field : fieldList) {
if (field.isAnnotationPresent(HeaderBelongType.class)) {
HeaderBelongType annotation = field.getAnnotation(HeaderBelongType.class);
String[] type = annotation.type();
List<String> list = null;
if (!(type.length == 1 && StringUtils.isBlank(type[0]))) {
list = Arrays.asList(type);
}
List<String> modelList = null;
boolean contains = true;
if (StringUtils.isNotBlank(model)) {
String[] models = annotation.model();
if (models.length == 1 && StringUtils.isBlank(models[0])) {
contains = true;
} else {
modelList = Arrays.asList(models);
contains = CollUtil.isEmpty(modelList) || modelList.contains(model);
}
}
if (CollUtil.isEmpty(list) || list.contains(headerBelongType)) {
if (!contains) {
continue;
}
headerInfo = new HeaderInfo();
headerInfo.setHeaderCode(field.getName());
ApiModelProperty property = field.getAnnotation(ApiModelProperty.class);
if (null == property) {
Asserts.fail("请为字段添加@ApiModelProperty注解");
}
headerInfo.setHeaderName(property.value());
lists.add(headerInfo);
}
}
}
return lists;
}
}
4)实体示例
@Data
@ApiModel("自助风险评估列表实体")
public class CalcInfoDTO {
@ApiModelProperty("生长期")
@HeaderBelongType()
private String growingSeason;
@ApiModelProperty("过程最低气温(℃)")
@HeaderBelongType(type = {RiskAssessmentTypeConstant.FREEZE_INJURY}, model = {EvaluationModelTypeConstant.FUZZY_INFERENCE_MODEL, EvaluationModelTypeConstant.SMALL_SAMPLE_INFORMATION_DIFFUSION})
private Float freProcessMinTemperature;
@ApiModelProperty("过程平均日最低气温(℃)")
@HeaderBelongType(type = {RiskAssessmentTypeConstant.FREEZE_INJURY}, model = {EvaluationModelTypeConstant.FUZZY_INFERENCE_MODEL, EvaluationModelTypeConstant.SMALL_SAMPLE_INFORMATION_DIFFUSION})
private Float freProcessMeanDailyMinTemperature;
}
- Excel工具类
/**
* 自定义表头导出
*
* @param headerInfos 表头信息
* @param dataList 需要导出的内容
* @param fileName 文件名
*/
public static <T> void downloadCustomFile(List<HeaderInfo> headerInfos, List<T> dataList, String fileName) {
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
if (attributes == null) {
Asserts.fail("数据导出出现错误");
}
HttpServletResponse response = attributes.getResponse();
try {
List<List<String>> headList = getHeadList(headerInfos);
List<List<String>> outputList = getOutputList(headerInfos, dataList);
response.setCharacterEncoding("utf-8");
//mime类型
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Pragma", "No-cache");
response.setHeader("Content-disposition", "attachment;filename=" + ".xlsx");
// 设置文件名
String fileNamePath = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileNamePath + ".xlsx");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream())
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.head(headList)
// 设置 sheet
.autoCloseStream(Boolean.FALSE).sheet(fileName)
.doWrite(outputList);
} catch (Exception e) {
log.error("自定义表头下载文件失败", e);
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
try {
response.getWriter().println(JSON.toJSONString(CommonResult.failed("下载文件失败:" + e.getMessage())));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* 获取与表头对应的导出字段信息
*
* @param headerInfos 表头信息
* @param dataList 需要导出的实体信息
* @param <T>
* @return 与表头对应的导出字段信息集合
*/
private static <T> List<List<String>> getOutputList(List<HeaderInfo> headerInfos, List<T> dataList) {
List<List<String>> lists = new ArrayList<>();
try {
for (T object : dataList) {
List<String> result = new ArrayList<>();
for (HeaderInfo headerInfo : headerInfos) {
Field field = object.getClass().getDeclaredField(headerInfo.getHeaderCode());
field.setAccessible(true);
Object o = field.get(object);
result.add(o.toString());
}
lists.add(result);
}
} catch (Exception e) {
log.error("获取导出数据信息失败", e);
Asserts.fail("获取导出数据信息失败");
}
return lists;
}
/**
* 获取表头信息
*
* @param headerInfos 表头信息
* @return excel表头信息
*/
public static List<List<String>> getHeadList(List<HeaderInfo> headerInfos) {
if (CollectionUtils.isEmpty(headerInfos)) {
Asserts.fail("表头信息不能为空!");
}
List<List<String>> heads = Lists.newArrayList();
for (HeaderInfo head : headerInfos) {
heads.add(Lists.newArrayList(head.getHeaderName()));
}
return heads;
}
- 使用示例
// 工具类获取实体注解表头
List<HeaderInfo> filedHeaderInfos = HeaderUtil.getObjectHeader(req.getEvaluationTypeCode(), modelService.specifyingComputationalModel(), CalcInfoDTO.class);
// 自定义表头
// 风险值
HeaderInfo assessedValue = new HeaderInfo();
assessedValue.setHeaderCode("assessedValue");
assessedValue.setHeaderName("风险值");
filedHeaderInfos.add(assessedValue);
// 风险等级
HeaderInfo riskLevelName = new HeaderInfo();
riskLevelName.setHeaderCode("riskLevelName");
riskLevelName.setHeaderName("风险等级");
filedHeaderInfos.add(riskLevelName);
List<HeaderInfo> headerInfos = new ArrayList<>();
// 地区
HeaderInfo area = new HeaderInfo();
area.setHeaderCode("areaFullName");
area.setHeaderName("地区");
headerInfos.add(area);
headerInfos.addAll(filedHeaderInfos);
// 需要导出的内容集合
List<CalcInfoDTO> lists = new ArrayList<>();
ExportUtils.downloadCustomFile(headerInfos, lists, riskName + "气象风险自助评估结果");