动态表头定位:前端导出Excel时,选择需要导出的字段。
在这里插入图片描述
实现思路:使用 自定义注解 ,映射 实体类字段和表头名称,再通过反射获取到实体类的自定义注解,对比 前端带过来的 表头集合,通过 hutool导出功能实现。

  1. 导入 相关依赖
        <!--    hutool 工具依赖    -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.3</version>
        </dependency>
        <!--    poi 相关依赖    -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version>
        </dependency>

这里说明一下导入了 poi-ooxml 依赖,因为这个是 hutool 要求的,可以在 ExcelUtil 类中看到
在这里插入图片描述

  1. 自定义注解
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HeaderName {
    String value() default "";
}
  1. 实体类使用 自定义注解 ,映射表头。注意: 这里的 字段顺序 和 导出Excel 后表头顺序是一致的
public class Album {
    @HeaderName("编号")
    private Long id;
    @HeaderName("相册名称")
    private String title;
    @HeaderName("相册封面")
    private String image;
    @HeaderName("图片列表")
    private String imageItems;
    // Getter and Setter 省略。。。
    }
  1. 封装hutool导出Excel工具类(HuTool参考文档)
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

public class HuToolExcelUtil {
    /**
     * 封装 通用导出方法
     * @param response
     * @param dataList
     * @param fileName
     */
    public static void universalExcelExport(HttpServletResponse response, List<Map<String, Object>> dataList, String fileName) {
        BigExcelWriter writer = (BigExcelWriter) ExcelUtil.getBigWriter();
        ServletOutputStream out = null;
        try {
            writer.write(dataList, true);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            writer.close();
            IoUtil.close(writer);
        }
    }
}
  1. 导出业务类 编写(相关的mapper 我就不粘出来了,我这里直接查询的 全部数据,需求不同可以条件查找之类的)
@Service
public class AlbumService {
    @Resource
    private AlbumMapper albumMapper;
    /**
     * 相册数据导出
     * @param response
     * @param names
     * @throws IllegalAccessException
     */
    public void export(HttpServletResponse response, List<String> names) throws IllegalAccessException {
        // 获取全部数据
        List<Album> albums = albumMapper.selectByExample(null);
        // 封装 hutool 导出需要的 数据格式。String:表头;Object:数据
        List<Map<String, Object>> dataMap = new LinkedList<>();
        for (Album album : albums) {
            // 实体类 转 Map
            Map<String, Object> entityMap = entityToMap(album, names);
            dataMap.add(entityMap);
        }
        HuToolExcelUtil.universalExcelExport(response,dataMap,"相册数据");
    }
	/**
     * 数据封装
     * @param album
     * @param names
     * @return
     * @throws IllegalAccessException
     */
    private Map<String, Object> entityToMap(Album album, List<String> names) throws IllegalAccessException {
        Map<String, Object> resMap = new LinkedHashMap<>();
        Class<?> albumClass = album.getClass();
        // 获取 实体类 中所有的字段
        Field[] declaredFields = albumClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
        	// 这里设置为 true 才可以访问到 实体类中的 private 字段
        	declaredField.setAccessible(true);
            // 获取字段所对应的注解
            HeaderName annotation = declaredField.getAnnotation(HeaderName.class);
            if (null != annotation){
                // 有注解 则 获取 注解的值(表头名称)
                String value = annotation.value();
                // 再判断 实体类中是否有这个表头
                if (names.contains(value)){
                    resMap.put(value,declaredField.get(album));
                }
            }
        }
        return resMap;
    }
}
  1. 导出Controller 编写
@RestController
@RequestMapping("/album")
public class AlbumController {
	@PostMapping("/export")
    public void export(HttpServletResponse response,@RequestBody List<String> names) throws IllegalAccessException {
        albumService.export(response,names);
    }
}
  1. 测试
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 结束啦!
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐