【实践记录】数据库数据通过POI生成Excel,并用JavaMail将此文件发送到指定邮箱


引入

接触数据库的时候,有时候需要将其中的一些数据导出来,生成Excel文件存档;有时候又需要将这Excel文件通过邮件的方式发送到指定的邮箱去。那么,这些需求,都该如何实现呢?


知识点归纳(方法步骤)

1.数据库设计、连接

关于数据库的设计和如何连接,在上一篇实践记录【实践记录】Java操作MySQL数据库——不定条件参数查询中已经有了必要的叙述,这里就不再重复,就以这个数据库为基础,进行进一步功能的实现。

数据库示例.png

2.通过POI生成Excel文件

要点:
(1)什么是POI:
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
(2)需要POI的JAR包:本人用的是poi-3.14-20160307,可去Apache的网站上下载Apache POI
(3)先初始化整份Excel工作薄workbook,再获得表sheet,再从中获得行row,才能获得单元格cell。根据实际情况使用循环。

Excel对象与POI类对应关系.png

(4)数据对应关系:POI类从0开始的,例如Excel的1行对应POI类的0行。

数据对应关系.png

(5)代码实现:
从数据库中获取需要导出的对象user的集合usersList

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import demo.pojo.Users;
import util.DBUtil;

public class UsersDAO {
    public static List<Users> getList() throws SQLException{
        //获取数据库连接
        Connection conn = DBUtil.getConnection();       
        List<Users> usersList = new ArrayList<Users>();
        String sql = "select * from users";
        //执行SQL语句
        PreparedStatement ps =conn.prepareStatement(sql); 
        ResultSet rs = ps.executeQuery();
        //提取查询结果
        Users user = null;
        while(rs.next()){
            user = new Users();
            user.setId(rs.getInt("u_id"));
            user.setName(rs.getString("u_name"));
            user.setIntroduce(rs.getString("u_introduce"));
            user.setFocusNum(rs.getLong("u_num_focus"));
            user.setFansNum(rs.getLong("u_num_fans"));
            user.setArticlesNum(rs.getLong("u_num_ariticles"));
            user.setWordsNum(rs.getLong("u_num_words"));
            user.setLikeNum(rs.getLong("u_num_like"));
                    
            usersList.add(user);
            }
        return usersList;
    }
}

编写生成Excel文件的方法write

import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import demo.dao.UsersDAO;
import demo.pojo.Users;

public class WriteExcel {
    
    public static void write(OutputStream outputStream) throws SQLException{
        //初始一个workbook
        HSSFWorkbook workbook = new HSSFWorkbook();
        List<Users> usersList = UsersDAO.getList();
        //创建单个sheet
        HSSFSheet sheet = workbook.createSheet("sheet0");
        //创建多行
        //创建第一行,设置列名
        HSSFRow row0 = sheet.createRow(0);
        for(int cellIndex = 0;cellIndex < 8;cellIndex++){
            HSSFCell cell = row0.createCell(cellIndex);
            switch(cellIndex){
            case 0:
                cell.setCellValue("ID");
                break;
            case 1:
                cell.setCellValue("姓名");
                break;
            case 2:
                cell.setCellValue("个人简介");
                break;
            case 3:
                cell.setCellValue("关注人数");
                break;
            case 4:
                cell.setCellValue("粉丝数");
                break;
            case 5:
                cell.setCellValue("文章数");
                break;
            case 6:
                cell.setCellValue("字数");
                break;
            case 7:
                cell.setCellValue("收获喜欢数");
                break;
            }
        } 
        //创建剩余行
        for(int rowIndex = 1;rowIndex <= usersList.size();rowIndex++){
            HSSFRow row = sheet.createRow(rowIndex);
            Users user = usersList.get(rowIndex-1);
            //创建多列
            for(int cellIndex = 0;cellIndex < 8;cellIndex++){
                HSSFCell cell = row.createCell(cellIndex);
                switch(cellIndex){
                case 0:
                    cell.setCellValue(user.getId());
                    break;
                case 1:
                    cell.setCellValue(user.getName());
                    break;
                case 2:
                    cell.setCellValue(user.getIntroduce());
                    break;
                case 3:
                    cell.setCellValue(user.getFocusNum());
                    break;
                case 4:
                    cell.setCellValue(user.getFansNum());
                    break;
                case 5:
                    cell.setCellValue(user.getArticlesNum());
                    break;
                case 6:
                    cell.setCellValue(user.getWordsNum());
                    break;
                case 7:
                    cell.setCellValue(user.getLikeNum());
                    break;
                }
            } 
        }
        
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

调用write方法生成Excel文件

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;

import util.WriteExcel;

public class POI_Test {
    public static void main(String[] args) {
        OutputStream out = null;
        try {
            out = new FileOutputStream(new File("E:\\jianshu.xls"));
            WriteExcel.write(out);
             
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
            if(out !=null){
                try {
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

生成的Excel文件如图:


Excel示例.png
3.通过JavaMail发送邮件

要点:
(1)JavaMail是由Sun定义的一套收发电子邮件的API。
(2)必要JAR包:本人用的是javax.mail-1.5.6,下载地址:Java Mail API
(3)邮件传输协议有很多种,这里使用smtp简单邮件传输协议
(4)连接邮件服务器的时候得注意,方法trans.connect("smtp.163.com", "xxxxxxxx", "xxxxxxxx");第一个参数是邮件服务器;第二个参数是163邮箱账号,这个账号是不带域名的,即没有@163.com后缀的;第三个参数就是密码。
(5)发件邮箱归属要与邮件服务器归属一致,例如我用163邮箱发邮件,那指定的邮件服务器就为smtp.163.com。发件邮箱就可以随意。
(6)代码实现:

import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class SendMailUtil {
    /*
     * 发送邮件到指定邮箱
     */
    public static void send(String fromAddress,String toAddress) throws Exception{
        /*
         * 第一步:创建Session,包含邮件服务器网络连接信息
         */
        Properties props = new Properties();
        //指定邮件的传输协议,smtp;同时通过验证
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.smtp.auth","true");
        Session session = Session.getDefaultInstance(props);
        //开启调试模式
        session.setDebug(true);
        /*
         * 第二步:编辑邮件内容
         */
        Message message = new MimeMessage(session);
        //设置邮件消息头
        message.setFrom(new InternetAddress(fromAddress));
        message.setRecipients(RecipientType.TO, InternetAddress.parse(toAddress));
        message.setSubject("JavaMail邮件测试");
        //设置邮件消息内容、包含附件
        Multipart msgPart = new MimeMultipart();
        message.setContent(msgPart);
        
        MimeBodyPart body = new MimeBodyPart(); //正文
        MimeBodyPart attach = new MimeBodyPart(); //附件
        
        msgPart.addBodyPart(body);
        msgPart.addBodyPart(attach);
        
        //设置正文内容
        body.setContent("JavaMail功能测试", "text/html;charset=utf-8");
        //设置附件内容
        attach.setDataHandler(new DataHandler(new FileDataSource("E:\\jianshu.xls")));
        attach.setFileName("简书用户数据.xls");
        
        message.saveChanges();
        /*
         * 第三步:发送邮件
         */
        Transport trans = session.getTransport();
        trans.connect("smtp.163.com", "xxxxxxxx", "xxxxxxxx");
        trans.sendMessage(message, message.getAllRecipients());

    }
    
    public static void main(String[] args) throws Exception {
        SendMailUtil.send("xxxxxxx@163.com","xxxxxxx@163.com");
    }
}

注意事项

1.这次实践生成Excel的操作其实只是POI的冰山一角,还可以利用POI对Excel文档进行各种常用操作,但不在本次实践范围内,所以不做拓展,有时间再去深入了解。
2.邮件传输概念也很复杂,深入的话也得花很多时间。JavaMail只是一套开放的API,辅助我们进行邮件传输的相关开发而已。而且,用到邮件服务器,就会受到邮件服务器的很多限制,例如本次实践过程中发送的测试邮件就多次被163误判为垃圾邮件(出错会有错误代码,去163退信规则里面看)。可能是没有遵循163的发信规则吧,后来调了很久,最终改了编辑邮件内容的代码才正常发送邮件。貌似也可以自己搭邮件服务器,不过还没有接触,有兴趣可以多去Google

相关参考

POI操作Excel常用方法总结
超详细POI实例:Java开发MS Excel
POI导出EXCEL经典实现
Java邮件开发(二):使用JMail发送一封图文并茂且包含附件的邮件(下)
JavaMail发送和接收邮件(JavaMailAPI说明)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容