最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)excel生成并且通過郵件發(fā)送的步驟詳解

 更新時(shí)間:2023年10月31日 09:38:34   作者:java大能蟲  
實(shí)際開發(fā)中,特別是在B端產(chǎn)品的開發(fā)中,我們經(jīng)常會(huì)遇到導(dǎo)出excel的功能,更進(jìn)階一點(diǎn)的需要我們定期生成統(tǒng)計(jì)報(bào)表,然后通過郵箱發(fā)送給指定的人員,?今天要帶大家來實(shí)現(xiàn)的就是excel生成并通過郵件發(fā)送,需要的朋友可以參考下

1. 開發(fā)環(huán)境

以下演示jdk選用1.8版本。springboot采用2.3.7.RELEASE版本。

excel生成通過alibaba的EasyExcel組件來實(shí)現(xiàn),采用最新的穩(wěn)定版本3.1.1

2. 思路

我們的核心實(shí)現(xiàn)分成兩步: 1、生成一個(gè)excel 2、將excel作為附件添加到郵件中進(jìn)行發(fā)送

于是基于此思路,我們結(jié)合EasyExcel提供的write方法來生成excel文件,該excel文件在郵件發(fā)送完成后需要?jiǎng)h除;然后通過之前我們講解過的郵件發(fā)送工具類來實(shí)現(xiàn)郵件發(fā)送

3. 實(shí)操

1、書寫郵件發(fā)送工具類,其實(shí)現(xiàn)參考上述博文

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.1</version>
</dependency>

3、實(shí)現(xiàn)easyExcel的數(shù)據(jù)監(jiān)聽類

/**
 * @author benjamin_5
 * @Description 數(shù)據(jù)監(jiān)聽類
 * @date 2022/10/5
 */
@EqualsAndHashCode(callSuper = true)
public class DataListener<T> extends AnalysisEventListener<T> {

    /**
     * 緩存數(shù)據(jù)列表
     */
    private final List<T> dataList = new ArrayList<>();

    @Override
    public void invoke(T data, AnalysisContext context) {
        dataList.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        this.invokeHeadMap(ConverterUtils.convertToStringMap(headMap,context),context);
    }

    public List<T> getDataList() {
        return dataList;
    }

}

4、創(chuàng)建生成excel文件的工具類ExcelUtil

public class ExcelUtil {

    /**
     * 生成excel文件
     * @param fileName excel文件路徑
     * @param dataList 數(shù)據(jù)列表
     * @param clazz 導(dǎo)出對(duì)象類
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> File generateExcel(String fileName, List<T> dataList, Class<T> clazz) throws IOException {
        // 生成文件
        File excel = new File(fileName);
        // excel寫入
        EasyExcel.write(excel,clazz).sheet(0).doWrite(dataList);
        return excel;
    }
}

5、創(chuàng)建導(dǎo)出數(shù)據(jù)的實(shí)體類

/**
 * @author benjamin_5
 * @Description
 * @date 2022/10/5
 */
@Data
public class CustomerData implements Serializable {

    @ExcelProperty(value = "客戶名稱")
    @ColumnWidth(value = 25)
    private String name;

    @ExcelProperty(value = "客戶地址")
    @ColumnWidth(value = 50)
    private String address;

    @ExcelProperty(value = "聯(lián)系電話")
    private String phone;

    @ExcelProperty(value = "金額")
    private BigDecimal amount;

    @ExcelProperty(value = "注冊(cè)日期")
    @DateTimeFormat(value = "yyyy-MM-dd")
    private Date createDate;
}

6、實(shí)現(xiàn)excel數(shù)據(jù)生成及郵件發(fā)送的接口。為了演示方便我直接在controller中書寫了,實(shí)際工作中應(yīng)該把生成并發(fā)送的方法提取到工具類或者Service層中。

這里調(diào)用的是基于spring-boot-starter-mail實(shí)現(xiàn)的郵件發(fā)送工具類

@GetMapping("generateExcelAndSend")
    public void generateExcelAndSend(){
        List<CustomerData> dataList = new ArrayList<>();
        // 構(gòu)造假數(shù)據(jù)
        for (int i = 0; i < 100; i++) {
            CustomerData data = new CustomerData();
            data.setName("客戶"+i);
            data.setAddress("貴州省貴陽市觀山湖區(qū)101號(hào)");
            data.setPhone("13889999999");
            data.setAmount(BigDecimal.valueOf(Math.random()*10000));
            data.setCreateDate(new Date());
            dataList.add(data);
        }
        // 獲取資源文件存放路徑,用于臨時(shí)存放生成的excel文件
        String path = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
        // 文件名:采用UUID,防止多線程同時(shí)生成導(dǎo)致的文件重名
        String fileName = String.format("%s客戶統(tǒng)計(jì)數(shù)據(jù)-%s.xlsx",path,UUID.randomUUID());
        try {
            // 生成excel文件
            File excel = ExcelUtil.generateExcel(fileName, dataList, CustomerData.class);
            // 發(fā)送郵件
            String content = "";
            String toMail = "wuhanxue5@sina.com";
            String ccMail = "wuhanxue5@163.com";
            emailSpringUtil.sendEmail("客戶統(tǒng)計(jì)數(shù)據(jù)",content,true,"郵件提醒系統(tǒng)",
                    toMail,ccMail,null, Collections.singletonList(fileName));
            // 郵件發(fā)送完成后刪除臨時(shí)生成的excel文件
            excel.delete();
        } catch (IOException e) {
            logger.error(String.format("生成excel失敗,原因:%s",e));
            e.printStackTrace();
        } catch (MessagingException e) {
            logger.error(String.format("郵件發(fā)送失敗,原因:%s",e));
            e.printStackTrace();
        }
    }

7、同時(shí)因?yàn)槲覀兊母郊Q后面添加一個(gè)了個(gè)UUID,mime.mail中的參數(shù)splitlongparameters默認(rèn)為 true,當(dāng)附件名過長(zhǎng)時(shí),他會(huì)自動(dòng)截取,就會(huì)導(dǎo)致我們接收到的附件格式變成.bin形式的。

要解決該問題就需要將其設(shè)置為false。于是我們創(chuàng)建一個(gè)啟動(dòng)執(zhí)行類來單獨(dú)設(shè)置

@Configuration
public class EmailToLongConfig {

    @PostConstruct
    private void init(){
        // 解決郵件附件名稱太長(zhǎng)會(huì)自動(dòng)截取,導(dǎo)致附件變成.bin格式問題
        System.setProperty("mail.mime.splitlongparameters","false");
    }
}

當(dāng)然我們也可以將System.setProperty("
mail.mime.splitlongparameters","false");放到郵件發(fā)送的方法中去。

8、啟動(dòng)項(xiàng)目,瀏覽器訪問接口測(cè)試

http://localhost:8080/excel/generateExcelAndSend

可以看到上述郵件發(fā)送成功,excel附件也接收正常,查看附件內(nèi)容也正常

優(yōu)化

上述的實(shí)現(xiàn),需要先創(chuàng)建一個(gè)文件然后又刪除,不是很方便,我們可以采取直接用流輸入輸出

1、首先生成excel的方法調(diào)整為返回輸出流

public static <T> ByteArrayOutputStream generateExcel(List<T> dataList, Class<T> clazz) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // excel寫入
        EasyExcel.write(out,clazz).sheet(0).doWrite(dataList);
        return out;
    } 

2、其次發(fā)送郵件的方法調(diào)整為,直接接收輸入流

public void sendEmail(String subject, String content, boolean contentIsHtml, String fromMailPersonalName,
                          String toMail, String ccMail, String bccMail, String fileName, InputStreamSource fileInput) throws MessagingException, UnsupportedEncodingException {
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(mailProperties.getUsername(), fromMailPersonalName);
        helper.setTo(toMail);
        if (!ObjectUtils.isEmpty(ccMail)) {
            helper.setCc(ccMail);
        }
        if (!ObjectUtils.isEmpty(bccMail)) {
            helper.setBcc(bccMail);
        }
        helper.setSubject(subject);
        helper.setText(content, contentIsHtml);
        // 設(shè)置附件(注意這里的fileName必須是服務(wù)器本地文件名,不能是遠(yuǎn)程文件鏈接)
        if (fileInput != null) {
            helper.addAttachment(fileName, fileInput);
        }
        javaMailSender.send(message);
    }

3、主方法調(diào)整:不生成文件,而是通過流來傳輸

@GetMapping("generateExcelAndSend2")
    public void generateExcelAndSend2() throws IOException {
        long start = System.currentTimeMillis();
        List<CustomerData> dataList = new ArrayList<>();
        // 構(gòu)造假數(shù)據(jù)
        for (int i = 0; i < 100; i++) {
            CustomerData data = new CustomerData();
            data.setName("客戶"+i);
            data.setAddress("貴州省貴陽市觀山湖區(qū)101號(hào)");
            data.setPhone("13889999999");
            data.setAmount(BigDecimal.valueOf(Math.random()*10000));
            data.setCreateDate(new Date());
            dataList.add(data);
        }
        // 獲取資源文件存放路徑,用于臨時(shí)存放生成的excel文件
        String path = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
        // 文件名:采用UUID,防止多線程同時(shí)生成導(dǎo)致的文件重名
        String fileName = String.format("%s客戶統(tǒng)計(jì)數(shù)據(jù)-%s.xlsx",path,UUID.randomUUID());
        ByteArrayOutputStream out = null;
        try {
            // 生成excel文件
            out = ExcelUtil.generateExcel(dataList, CustomerData.class);
            // 發(fā)送郵件
            String content = "客戶統(tǒng)計(jì)數(shù)據(jù)如附件所示";
            String toMail = "wuhanxue5@sina.com";
            String ccMail = "wuhanxue5@163.com";
            emailSpringUtil.sendEmail("客戶統(tǒng)計(jì)數(shù)據(jù)",content,false,"郵件提醒系統(tǒng)",
                    toMail,ccMail,null, fileName, new ByteArrayResource(out.toByteArray()));
        } catch (IOException e) {
            logger.error(String.format("生成excel失敗,原因:%s",e));
            e.printStackTrace();
        } catch (MessagingException e) {
            logger.error(String.format("郵件發(fā)送失敗,原因:%s",e));
            e.printStackTrace();
        }finally {
            if(out != null){
                out.close();
            }
            long end = System.currentTimeMillis();
            System.out.println("耗時(shí):" + (end - start));
        }
    } 

4、最終測(cè)試下來,第二種方法要比之前方法快600ms左右

郵件正文中直接顯示表格數(shù)據(jù)

有時(shí)候我們的統(tǒng)計(jì)數(shù)據(jù)不是很多,會(huì)更希望我們直接在郵件中展示表格數(shù)據(jù),而不用再單獨(dú)下載附件查看,這就需要用到HTML格式的郵件正文的實(shí)現(xiàn)

比較簡(jiǎn)單的實(shí)現(xiàn)就是循環(huán)數(shù)據(jù)集合,通過字符串拼接生成html的字符串。因?yàn)閷?shí)現(xiàn)比較簡(jiǎn)單,這里就僅提供思路,如果有不清楚的同學(xué)可以留言提問。后續(xù)我們單獨(dú)抽離成一個(gè)組件來實(shí)現(xiàn)生成html字符串的功能

總結(jié)

excel的生成以及郵件的發(fā)送,都應(yīng)該盡可能的提取為工具類,如果實(shí)現(xiàn)的功能更多的更需要提取的單獨(dú)的服務(wù),通過pom依賴引入,更大化的實(shí)現(xiàn)方法的通用,和業(yè)務(wù)代碼與通用代碼之間的解耦。

以上就是SpringBoot實(shí)現(xiàn)excel生成并且通過郵件發(fā)送的步驟詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot實(shí)現(xiàn)excel生成的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 識(shí)別率很高的java文字識(shí)別技術(shù)

    識(shí)別率很高的java文字識(shí)別技術(shù)

    這篇文章主要為大家詳細(xì)介紹了識(shí)別率很高的java文字識(shí)別技術(shù),親測(cè),希望對(duì)大家有幫助,感興趣的小伙伴們可以參考一下
    2016-08-08
  • java ant 配置及構(gòu)建項(xiàng)目圖文教程

    java ant 配置及構(gòu)建項(xiàng)目圖文教程

    以下是對(duì)java ant配置及構(gòu)建項(xiàng)目進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • SWT(JFace)體驗(yàn)之ProgressBar

    SWT(JFace)體驗(yàn)之ProgressBar

    SWT(JFace)體驗(yàn)之ProgressBar 實(shí)現(xiàn)代碼。
    2009-06-06
  • SpringBoot集成Open WebUI實(shí)現(xiàn)AI流式對(duì)話

    SpringBoot集成Open WebUI實(shí)現(xiàn)AI流式對(duì)話

    本文介紹如何在 Spring Boot 項(xiàng)目中集成 Open WebUI,通過自動(dòng)管理用戶 Token、調(diào)用 OpenAI Java SDK,實(shí)現(xiàn) SSE 流式輸出,并與前端文本輸入框無縫對(duì)接,為業(yè)務(wù)系統(tǒng)注入 AI 能力,需要的朋友可以參考下
    2026-05-05
  • Java IO流相關(guān)知識(shí)代碼解析

    Java IO流相關(guān)知識(shí)代碼解析

    這篇文章主要介紹了Java IO流相關(guān)知識(shí)代碼解析,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • java 啟動(dòng)exe程序,傳遞參數(shù)和獲取參數(shù)操作

    java 啟動(dòng)exe程序,傳遞參數(shù)和獲取參數(shù)操作

    這篇文章主要介紹了java 啟動(dòng)exe程序,傳遞參數(shù)和獲取參數(shù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Maven?pom.xml文件獲取當(dāng)前時(shí)間戳方式

    Maven?pom.xml文件獲取當(dāng)前時(shí)間戳方式

    這篇文章主要介紹了Maven?pom.xml文件獲取當(dāng)前時(shí)間戳方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java多線程之等待隊(duì)列DelayQueue詳解

    Java多線程之等待隊(duì)列DelayQueue詳解

    這篇文章主要介紹了Java多線程之等待隊(duì)列DelayQueue詳解,    DelayQueue被稱作"等待隊(duì)列"或"JDK延遲隊(duì)列",存放著實(shí)現(xiàn)了Delayed接口的對(duì)象,對(duì)象需要設(shè)置到期時(shí)間,當(dāng)且僅當(dāng)對(duì)象到期,才能夠從隊(duì)列中被取走(并非一定被取走),需要的朋友可以參考下
    2023-12-12
  • java實(shí)現(xiàn)簡(jiǎn)易的五子棋游戲

    java實(shí)現(xiàn)簡(jiǎn)易的五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)易的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Java中的自定義異常實(shí)現(xiàn)方式

    Java中的自定義異常實(shí)現(xiàn)方式

    這篇文章主要介紹了Java中的自定義異常實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04

最新評(píng)論

郎溪县| 永安市| 樟树市| 普安县| 饶平县| 瑞丽市| 龙井市| 太康县| 府谷县| 昌都县| 通道| 大方县| 灵寿县| 镇坪县| 梁平县| 北安市| 天气| 文登市| 阿坝| 莎车县| 隆子县| 大石桥市| 仪陇县| 隆德县| 西藏| 余庆县| 贺兰县| 平凉市| 古田县| 平顶山市| 康定县| 博湖县| 梨树县| 台州市| 鄂托克旗| 资溪县| 临湘市| 文登市| 怀远县| 永城市| 沈丘县|