【軟件工具】easyExcel簡明使用指南

easyExcel簡介

Java領域解析、生成Excel比較有名的框架有Apache poi、jxl等。但他們都存在一個嚴重的問題就是很是的耗內存。若是你的系統併發量不大的話可能還行,可是一旦併發上來後必定會OOM或者JVM頻繁的full gc。html

easyExcel是阿里巴巴開源的一個excel處理框架,以使用簡單、節省內存著稱java

64M內存1分鐘內讀取75M(46W行25列)的Excel(固然還有急速模式能更快,可是內存佔用會在100M多一點)
git

easyExcel能大大減小佔用內存的主要緣由是在解析Excel時沒有將文件數據一次性所有加載到內存中,而是從磁盤上一行行讀取數據,逐個解析。github

下圖是easyExcel和POI在解析Excel時的對比圖。
web

easyExcel採用一行一行的解析模式,並將一行的解析結果以觀察者的模式通知處理(AnalysisEventListener)。spring

上面簡要介紹了easyExcel的特色和原理,關於easyExcel的其餘問題能夠先參考下這個文章。下面就經過代碼來介紹下怎麼使用easyExcel。數據庫

快速使用指南

文件上傳讀取Excel

下面經過一個讀取用戶信息的列子來展現下怎麼使用easyExcel。安全

step1:建立用戶信息類併發

@Data
public class UserInfo extends BaseRowModel {

    @ExcelProperty(index = 0)
    private String name;

    @ExcelProperty(index = 1)
    private int age;

    @ExcelProperty(index = 2)
    private String address;

}

step2:建立AnalysisEventListener子類app

/**
 * 每解析一行會回調invoke()方法。
 * 整個excel解析結束會執行doAfterAllAnalysed()方法
 */

//有個很重要的點   不能被spring管理,要每次讀取excel都要new。
//這邊就會有一個問題:若是UserInfoDataListener中須要用到Spring中的主鍵怎麼辦?
public class UserInfoDataListener extends AnalysisEventListener<UserInfo> {

    Logger logger = LoggerFactory.getLogger(UserInfoDataListener.class);

    //每次讀取100條數據就進行保存操做
    private static final int BATCH_COUNT = 100;
    //因爲每次讀都是新new UserInfoDataListener的,因此這個list不會存在線程安全問題
    List<UserInfo> list = new ArrayList<>();

    //這個組件是Spring中的組件,這邊推薦兩種方法注入這個組件
    //第一種就是提供一個UserInfoDataListener的構造方法,這個方法提供一個參數是UserInfoDataListener類型
    //另一種方法就是將 UserInfoDataListener 這個類定義成 UserService 實現類的內部類(推薦這種方式)
    //private UserService userService;

    @Override
    public void invoke(UserInfo data, AnalysisContext analysisContext) {
        logger.info("解析到一條數據:{}", JSON.toJSONString(data));
        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存儲完成清理 list
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 這裏也要保存數據,確保最後遺留的數據也存儲到數據庫
        saveData();
        logger.info("全部數據解析完成!");
    }

    private void saveData() {
        logger.info("{}條數據,開始存儲數據庫!", list.size());
        //保存數據
        //userService.save(list);
        logger.info("存儲數據庫成功!");
    }

}

step3: 讀取excel

public class EasyExcelDemo {

    public static void main(String[] args) throws Exception {
        InputStream fis = new FileInputStream("D:\\UserInfo.xlsx");

        AnalysisEventListener listener = new UserInfoDataListener();

        ExcelReader excelReader = EasyExcel.read(fis, UserInfo.class, listener).build();
        ReadSheet readSheet = EasyExcel.readSheet(0).build();
        ReadSheet readSheet2 = EasyExcel.readSheet(1).build();
        excelReader.read(readSheet);
        // 這裏千萬別忘記關閉,讀的時候會建立臨時文件,到時磁盤會崩的
        excelReader.finish();
    }

}

只須要上面3步就能進行Excel的讀取了。

文件下載Excel

public class ExcelUtil {

    public static OutputStream getOutputStream(String fileName, HttpServletResponse response)
            throws Exception{
        try{
            fileName = URLEncoder.encode(fileName,"utf-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            //此處指定了文件類型爲xls,若是是xlsx的,請自行替換修改
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xls");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e){
            throw new Exception("導出文件失敗!");
        }
    }

    public static void writeExcel(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName,
                                  String sheetName, Class clazz) throws Exception {
        ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLS);
        Sheet sheet = new Sheet(1, 0, clazz);
        sheet.setSheetName(sheetName);
        writer.write(list, sheet);
        writer.finish();
    }

}

在Controller中咱們只要像下面這種方式調用就好了。

@RequestMapping(value = "/file/testExcelDownload")
    public void testExcelDownload(HttpServletRequest request,HttpServletResponse response){
        //如下信息從數據庫中查出
        List<ExcelInfo> excelInfos = new ArrayList<>();
        ExcelInfo info1 = new ExcelInfo();
        ExcelInfo info2 = new ExcelInfo();
        excelInfos.add(info1);
        excelInfos.add(info2);
        info1.setIssuerName("name1");
        info1.setRiskLevel("level1");
        info2.setIssuerName("name1");
        info2.setRiskLevel("level1");
        try {
            String fileName = "excelInfo";
            String sheetName = "sheet1";
            ExcelUtil.writeExcel(response, excelInfos, fileName, sheetName, ExcelInfo.class);
        } catch(Exception e){
            log.error("模板下載失敗",e);
        }

    }

在導出Excel的部分,easyExcel還提供了自定義樣式,插入表格,插入圖片等其餘功能,還有一個比較有意思的功能就是Excel模板填充的功能。詳細的功能信息參考官方文檔

相關文章
相關標籤/搜索