1、自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAttribute {

    String name() default "";
    
    int sort();
    
    Class<? extends ExportTypeHandler> typeHandler() default ExportTypeHandler.class;

}

2、自定义类型格式化Handler

import java.util.Date;
import java.util.Objects;


public class DateTypeHandler implements ExportTypeHandler{
    
    private static final String DATE_FORMAT = "yyyy-MM-dd";

    @Override
    public String getValue(Object value) throws Exception {
        if (Objects.isNull(value) || !(value instanceof Date)) {
            return "";
        } else {
            return DateUtils.format((Date) value, DATE_FORMAT);
        }
    }

}

3、导出方法实现

private static final Map<Class<? extends ExportTypeHandler>, ExportTypeHandler> TYPE_HANDLER_MAP = new HashMap<>();

private static final String ROW_NUMBER = "rowNum";

private static final String ROW_NUMBER_ALIAS = "序号";

/**

 * 导出Excel

 * @param request

 * @param response

 * @param title

 * @param records
   */
   public void exportExcel(HttpServletRequest request, HttpServletResponse response, String title, List<T> records) {
   ExcelSource<Map<String, Object>> excelSource = new ExcelSource<>();
   // excel 文件名称
   excelSource.setExcelName(title);
   // excel sheet名称
   excelSource.setSheetName(title);
   // excel表头组装
   Map<String, String> headerMap = new LinkedHashMap<>();
   Map<Integer, ExcelFieldDTO> fieldAliasMap = new HashMap<>();
   List<Map<String, Object>> data = new ArrayList<>();

   // 初始化行号
   int row = 1;

   if (CollectionUtils.isNotEmpty(records)) {
       for (T record : records) {
           Map<String, Object> rowDataMap = new LinkedHashMap<>();
           rowDataMap.put(ROW_NUMBER, String.valueOf(row));
           if (row == 1) {
               ExcelFieldDTO alias = new ExcelFieldDTO();
               alias.setField(ROW_NUMBER);
               alias.setAlias(ROW_NUMBER_ALIAS);
               fieldAliasMap.put(0, alias);
           }

           Field[] fields = record.getClass().getDeclaredFields();
           for (int i = 0; i < fields.length; i++) {
               Field field = fields[i];
               if (field.isAnnotationPresent(ExcelAttribute.class)) {
                   ExcelAttribute attribute = field.getAnnotation(ExcelAttribute.class);
                   if (row == 1) {
                       ExcelFieldDTO fieldAlias = new ExcelFieldDTO();
                       fieldAlias.setField(field.getName());
                       fieldAlias.setAlias(attribute.name());
                       fieldAliasMap.put(attribute.sort(), fieldAlias);
                   }
       
                   // 获取原值
                   field.setAccessible(true);
                   Object value = null;
                   try {
                       value = field.get(record);
                   } catch (IllegalAccessException e) {
                       log.error(e.getMessage(), e);
                   }
                   if (Objects.nonNull(attribute.typeHandler().getSuperclass()) && attribute.typeHandler().getSuperclass().isAssignableFrom(ExportTypeHandler.class)) {
                       // 重新赋值
                       rowDataMap.put(field.getName(), getValue(value, attribute.typeHandler()));
                   } else {
                       rowDataMap.put(field.getName(), value);
                   }
               }
           }
       
           // 行号加1
           row++;
           // 添加行数据
           data.add(rowDataMap);
       }


        fieldAliasMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(x -> headerMap.put(x.getValue().getField(), x.getValue().getAlias()));
    
        excelSource.setMergeHead(title);
        excelSource.setHeaderMap(headerMap);
        excelSource.setDataList(data);
    
        ExcelEnhanceHelper.exportExcel(request, response, excelSource);
    }

}
/**

 * 获取格式化后的值
 *
 * @param value
 * @param aClass
 * @return
   */
   private static Object getValue(Object value, Class<? extends ExportTypeHandler> aClass) {
   if (Objects.isNull(value)) {
       value = "";
   } else {
       ExportTypeHandler typeHandler;
       try {
           if (TYPE_HANDLER_MAP.containsKey(aClass)) {
               typeHandler = TYPE_HANDLER_MAP.get(aClass);
           } else {
               //如果TYPE_HANDLER_MAP内没有该class的实力 则通过反射创建一个并存入
               typeHandler = aClass.newInstance();
               TYPE_HANDLER_MAP.put(aClass, typeHandler);
           }
           //调用方法获得类型对应的value
           value = typeHandler.getValue(value);
       } catch (Exception e) {
           log.error("ExportTypeHandler转换失败,value:{},失败异常:", value, e);
       }
   }
   return value;
   }

4、导出实体添加ExcelAttribute注解

@Data
public class PersonDTO {

/**

 * 名称
   */
   @ExcelAttribute(name = "名称", sort = 1)
   private String name;

/**

 * 年龄
   */
   @ExcelAttribute(name = "年龄", sort = 2)
   private Integer age;

/**

 * 生日
   */
   @ExcelAttribute(name = "生日", sort = 3, typeHandler = DateTypeHandler.class)
   private Date birthday;

}

ExcelAttribute注解的name属性指定字段别名,通过sort属性指定字段先后顺序,若字段需要格式化通过typeHandler 属性指定要格式化的类,已经提供DateTypeHandler,扩展需实现ExportTypeHandler接口

5、导出调用

public void exportExcel(HttpServletRequest request, HttpServletResponse response, PageParam param) {
    List<PersonDTO> list = baseMapper.queryList(param);
    exportExcel(request, response, "XXXX", list);
}