cloud-security-wiki/docs/util/excel/README.md

7.5 KiB
Raw Blame History

Excel快速导出

功能介绍

  • 在对应实现类上加上自定义注解@Excel后,在编写web接口是调用ExcelUtil.exportExcel即可实现对应实体Excel的快速导出

实现原理

  • 主要使用到Java反射机制,获取到目标实体的Class对象后通过java发射获取到每个字段,并且获取到对应字段上的@Excel注解,将注解中的数据记录下来作为Excel中的表头。再通过java反射获取到对应的数据并做好与标表头的映射关系最终使用ease-excel实现Excel的渲染

代码展示

package cn.odliken.security.utils;

import cn.odliken.admin.api.entity.DictData;
import cn.odliken.admin.api.fegin.DictDataService;
import cn.odliken.common.core.constant.ResultConstant;
import cn.odliken.common.core.constant.SecurityConstants;
import cn.odliken.common.core.exception.CustomException;
import cn.odliken.common.core.result.Result;
import cn.odliken.common.core.utils.DateUtils;
import cn.odliken.common.core.utils.SpringContextHolder;
import cn.odliken.common.core.utils.StringUtils;
import cn.odliken.common.core.utils.reflect.ReflectUtils;
import cn.odliken.security.annotation.Excel;
import cn.odliken.security.annotation.Excels;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Clay
 * @date 2022/12/19
 */
public class ExcelUtil {

    public static List<ExcelAssist> assistList = new ArrayList<>();

    public static Map<String,Map<String,DictData>> dictDataMap;


    private static DictDataService getBean() {
        return SpringContextHolder.getBean(DictDataService.class);
    }

    /**
     * 获取到数据列表
     *
     * @param list
     * @return
     */
    private static List<List<Object>> getDataList(List<?> list) {
        return list.stream().map(object ->
                assistList.stream().map(assist -> {
                    Field field = assist.getField();
                    Excel excel = assist.getExcel();
                    Object value = null;
                    if (StringUtils.isEmpty(assist.getObjectFieldName())) {
                        value = getData(object, excel, field);
                    } else {
                        Object sunValue = null;
                        try {
                            sunValue = ReflectUtils.invokeGetter(object, assist.getObjectFieldName());
                        } catch (Exception e) {
                            return null;
                        }
                        if (null != sunValue) {
                            value = getData(object, excel, field);
                        }
                    }
                    return value;
                }).collect(Collectors.toList())
        ).collect(Collectors.toList());
    }

    /**
     * 获取到对象中的数据
     *
     * @param object
     * @param excel
     * @param field
     * @return
     */
    private static Object getData(Object object, Excel excel, Field field) {
        try {
            Object objectValue = ReflectUtils.invokeGetter(object, field.getName());
            if (objectValue instanceof Date) {
                objectValue = DateUtils.parseDateToStr(excel.dateFormat(), (Date) objectValue);
            }
            String dictType = excel.dictType();
            if (StringUtils.isNotEmpty(dictType)){
                Map<String,DictData> dictMap = dictDataMap.get(dictType);
                if (null != dictMap){
                    DictData dictData = dictMap.get(objectValue.toString());
                    if (null!= dictData){
                        objectValue = dictData.getDictLabel();
                    }
                }
            }
            return objectValue;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 初始化header数据
     *
     * @param clazz
     * @param assist
     */
    private static void initHeader(Class<?> clazz, ExcelAssist assist) {
        for (Field field : clazz.getDeclaredFields()) {
            Excel excel = field.getAnnotation(Excel.class);
            if (null != excel) {
                assistList.add(new ExcelAssist(field, excel, assist));
            } else {
                Excels excels = field.getAnnotation(Excels.class);
                if (excels == null) {
                    continue;
                }
                Class<?> objectValue = field.getType();
                if (clazz == objectValue) {
                    throw new CustomException("不允许嵌套对象导出Excel");
                }
                ExcelAssist excelAssist = new ExcelAssist(field, excels);
                initHeader(objectValue, excelAssist);
            }
        }
    }

    public static void exportExcel(List<?> list, Class<?> clazz) {
        exportExcel(list, clazz, null);
    }

    /**
     * 导出数据Excel
     *
     * @param list
     * @param clazz
     * @param sheetName
     */
    public static void exportExcel(List<?> list, Class<?> clazz, String sheetName) {
        Set<String> dictList = new HashSet<>();

        initHeader(clazz, null);
        List<List<String>> headerList = new ArrayList<>(assistList.size());
        assistList = assistList.stream().sorted(Comparator.comparing(ExcelAssist::getOrder))
                .peek(assist -> headerList.add(Collections.singletonList(assist.getExcel().value())))
                .peek(assist -> {
                    String dictType = assist.getExcel().dictType();
                    if (StringUtils.isNotEmpty(dictType)) {
                        dictList.add(dictType);
                    }
                })
                .collect(Collectors.toList());
        if (dictList.size() > 0) {
            getDictData(new ArrayList<>(dictList));
        }
        List<List<Object>> dataList = getDataList(list);
        try {
            sheetName = StringUtils.isEmpty(sheetName) ? "sheet" : sheetName;
            HttpServletResponse response = getResponse(sheetName);
            EasyExcel.write(response.getOutputStream())
                    .head(headerList)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet(StringUtils.isEmpty(sheetName) ? "sheet" : sheetName)
                    .doWrite(dataList);
        } catch (IOException e) {
            throw new CustomException("Excel导出失败!");
        }
    }


    private static HttpServletResponse getResponse(String sheetName){
        HttpServletResponse response = SecurityUtils.getResponse();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition" ,
                "attachment;fileName=" + sheetName + UUID.randomUUID() + ".xlsx");
        return response;
    }

    private static void getDictData(List<String> dictList) {
        DictDataService dictDataService = getBean();
        Result<Map<String, Map<String,DictData>>> result = dictDataService.searchDictDataCacheKeys(dictList, SecurityConstants.FROM_IN);
        System.out.println(result);
        if (result.getCode() == ResultConstant.SUCCESS_CODE){
            dictDataMap = result.getData();
        }
    }
}

使用demo

@ApiOperation("导出excel数据")
@GetMapping("/export")
@PreAuthorize("@ss.hasPermission('code:goods:export')")
public void export(DemoGoodsQuery query){
    List<DemoGoodsVo> list = demoGoodsService.exportDemoGoodsList(query);
    ExcelUtil.exportExcel(list,DemoGoodsVo.class);
}