【方向盤】版本歷史&代碼示例之:JavaMail、JDBC
前言
若你還不太清楚Java EE是什么,可先移步這里:什么是Java EE?
發郵件是企業級應用開發的剛性需求,如:每晚定時任務跑完后自動將結果數據發封郵件到領導郵箱供以查閱。郵件雖然“古老”,但相較于IM消息具有很多不可替代的優勢:
- 更為正式:相對重要的場合/數據用郵件更為合適
- 承載內容多:一封郵件的文本字數理論上無上限
- 格式豐富:可由附件、圖片、文本組合。支持HTML排版
- 發送形式豐富:除了收件人外,還可以抄送、密送
既然發郵件的場景這么常見,但據我經驗,每每遇到發郵件問題時,同事往往“頭疼不已”,你是否也有類似情況呢?本文就來聊聊JavaMail的發展歷程,然后給出一些代碼示例。
除此之外,本文還會聊聊更為重要的JDBC,它高頻的出現在各大面試場合里,是考驗一個求職者技術基礎水平的重要知識點,更是流行框架MyBatis的基石。
所屬專欄
【方向盤】-Java EE
相關下載
- 【本專欄源代碼】:https://github.com/yourbatman/FXP-java-ee
- 【女媧Knife-Initializr工程】訪問地址:http://152.136.106.14:8761
- 【程序員專用網盤】公益上線啦,注冊送1G超小容量,幫你實踐做減法:https://wangpan.yourbatman.cn
- 【Java開發軟件包(Mac)】:https://wangpan.yourbatman.cn/s/rEH0 提取碼:javakit
版本約定
- Java EE:6、7、8
- Jakarta EE:8、9、9.1
正文
JavaMail
JavaMail API提供了一個獨立于平臺和協議的框架來構建郵件和消息傳遞應用程序。JavaMail API作為可選包提供,可與Java SE平臺一起使用,也包含在JavaEE平臺中。
JavaMail 是sun公司為方便Java開發人員在應用程序中實現郵件發送和接收功能而提供的一套標準開發包,它支持一些常用的郵件協議,如SMTP,POP3,IMAP,還有MIME(發送附件)等。我們在使用JavaMail API 編寫郵件時,無須考慮郵件的底層實現細節,只要調用JavaMail 開發包中相應的API類就可以了。
- <!-- javax命名空間版本(Tomcat 9.x及以下版本支持) -->
- <dependency>
- <groupId>javax.mail</groupId>
- <artifactId>javax.mail-api</artifactId>
- <version>1.6.2</version>
- </dependency>
- <!-- jakarta命名空間版本(Tomcat 10.x及以上版本支持) -->
- <dependency>
- <groupId>jakarta.mail</groupId>
- <artifactId>jakarta.mail-api</artifactId>
- <version>2.0.1</version> <!-- 對應的參考實現為:com.sun.mail:jakarta.mail -->
- <!-- <version>1.6.7</version> 此版本命名空間同javax -->
- </dependency>
版本歷程
JavaMail的最新版本是1.6.2,于2018.08發布。
javax.mail-api.jar是JavaMail的API,一般無需單獨引入。即使需要引入,scope使用provide即可。com.sun.mail:javax.mail.jar是JavaMail的參考實現,包括SMTP、IMAP和POP3等常見協議的實現。
說明:“自古”傳出的發郵件需要導入兩個jar包,中的activtion.jar不是必須的,一個mail.jar大部分情況下就夠了
值得注意的是:借助Spring發送郵件,并沒有spring-mail獨立模塊(相關類在spring-context-support這個模塊里),只有Spring Boot提供的spring-boot-starter-mail獨立啟動器。
生存現狀
不可或缺,且已非常成熟。
實現(框架)
com.sun.mail:javax.mail或者com.sun.mail:jakarta.mail即為官方參考實現,Spring Boot也是使用它來發送郵件的。
代碼示例
生產環境當然建議使用Spring(or Spring Boot)提供的mail能力來發送郵件,非常簡單方便。本文加點料,直接使用底層API來試試。
JavaMail API 按照功能可以劃分為如下三大類:
- 創建和解析郵件的API
- 發送郵件的API
- 接收郵件的API
這三大類涉及到很多類,但核心的只有4個,也就是俗稱的JavaMail四大核心類。如下圖所示:
絕大部分情況下,我們只需使用JavaMail發送郵件即可,也就是三個類:
- Session:用于定義整個應用程序所需的環境信息。如主機名、端口、郵件協議等等
- Message:郵件內容。通常使用它的子類javax.mail.internet.MimeMessage 類。還有如SMTPMessage、SMTPMessage等等
- Transport:發送郵件的核心API 類
下面筆者使用JavaMail API發送一封郵件到自己的郵箱:yourbatman@aliyun.com,代碼如下。
準備基礎發送、接收人元信息:
- // =====發送者信息======
- public static final String SENDER_ADDRESS = "641385712@qq.com";
- public static final String SENDER_ACCOUNT = "641385712@qq.com";
- public static final String SENDER_PASSWORD = "xxxxxxxxxxxxx"; // QQ郵箱這里使用授權碼登錄,而不是密碼哦
- public static final String SENDER_QQ_SMTP_SERVER = "smtp.qq.com";
- // =====收件人信息======
- public static final String RECIPIENT_ADDRESS = "yourbatman@aliyun.com";
什么是QQ郵箱登錄授權碼?就是這個東東(具體怎么獲得,自己用谷歌百度一下):
調用API,書寫發送郵件的代碼:
- /**
- * 發送郵件
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- Properties props = new Properties();
- props.setProperty("mail.smtp.auth", "true"); //用戶的認證方式
- props.setProperty("mail.transport.protocol", "smtp"); // 傳輸協議
- props.setProperty("mail.smtp.host", SENDER_QQ_SMTP_SERVER); // 發件人的SMTP服務器地址
- Session session = Session.getInstance(props);
- session.setDebug(true); // 在控制臺打印調試信息
- // ======創建一封郵件======
- Message msg = createMimeMessage(session);
- // ======準備發送======
- Transport transport = session.getTransport();
- transport.connect(SENDER_ACCOUNT, SENDER_PASSWORD);
- transport.sendMessage(msg, msg.getAllRecipients()); // 發送郵件(包括)
- //如果只想發送給指定的人,可以如下寫法
- //transport.sendMessage(msg, new Address[]{new InternetAddress("xxx@qq.com")});
- transport.close();
- }
- private static MimeMessage createMimeMessage(Session session) throws Exception {
- MimeMessage msg = new MimeMessage(session);
- msg.setFrom(new InternetAddress(SENDER_ADDRESS)); // 設置發件人地址
- /**
- * 設置收件人地址(可以增加多個收件人、抄送、密送),即下面這一行代碼書寫多行
- * MimeMessage.RecipientType.TO:發送
- * MimeMessage.RecipientType.CC:抄送
- * MimeMessage.RecipientType.BCC:密送
- */
- msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(RECIPIENT_ADDRESS));
- msg.setSubject("我是郵件主題", "UTF-8");
- msg.setContent("我是簡單的純文本郵件!", "text/html;charset=UTF-8");
- msg.setSentDate(new Date()); // 郵件的發送時間,默認立即發送
- return msg;
- }
運行程序,收到郵件,完美!
控制臺的debug日志可以窺探這個發送過程:
- DEBUG: setDebug: Jakarta Mail version 1.6.7
- DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
- DEBUG SMTP: useEhlo true, useAuth true
- DEBUG SMTP: trying to connect to host "smtp.qq.com", port 25, isSSL false
- 220 newxmesmtplogicsvrszb6.qq.com XMail Esmtp QQ Mail Server.
- DEBUG SMTP: connected to host "smtp.qq.com", port: 25
- EHLO 192.168.0.145
- 250-newxmesmtplogicsvrszb6.qq.com
- 250-PIPELINING
- 250-SIZE 73400320
- 250-STARTTLS
- 250-AUTH LOGIN PLAIN XOAUTH XOAUTH2
- 250-AUTH=LOGIN
- 250-MAILCOMPRESS
- 250 8BITMIME
- DEBUG SMTP: Found extension "PIPELINING", arg ""
- DEBUG SMTP: Found extension "SIZE", arg "73400320"
- DEBUG SMTP: Found extension "STARTTLS", arg ""
- DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH XOAUTH2"
- DEBUG SMTP: Found extension "AUTH=LOGIN", arg ""
- DEBUG SMTP: Found extension "MAILCOMPRESS", arg ""
- DEBUG SMTP: Found extension "8BITMIME", arg ""
- DEBUG SMTP: protocolConnect login, host=smtp.qq.com, user=641385712@qq.com, password=<non-null>
- DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2
- DEBUG SMTP: Using mechanism LOGIN
- DEBUG SMTP: AUTH LOGIN command trace suppressed
- DEBUG SMTP: AUTH LOGIN succeeded
- DEBUG SMTP: use8bit false
- MAIL FROM:<641385712@qq.com>
- 250 OK.
- RCPT TO:<yourbatman@aliyun.com>
- 250 OK
- DEBUG SMTP: Verified Addresses
- DEBUG SMTP: yourbatman@aliyun.com
- DATA
- 354 End data with <CR><LF>.<CR><LF>.
- Date: Wed, 6 Oct 2021 20:37:54 +0800 (CST)
- From: 641385712@qq.com
- To: yourbatman@aliyun.com
- Message-ID: <683287027.0.1633523875105@[192.168.0.145]>
- Subject: =?UTF-8?B?5oiR5piv6YKu5Lu25Li76aKY?=
- MIME-Version: 1.0
- Content-Type: text/html;charset=UTF-8
- Content-Transfer-Encoding: base64
- 5oiR5piv566A5Y2V55qE57qv5paH5pys6YKu5Lu277yB
- .
- 250 OK: queued as.
- DEBUG SMTP: message successfully delivered to mail server
- QUIT
- 221 Bye.
- Process finished with exit code 0
本專欄源代碼:https://github.com/yourbatman/FXP-java-ee
JDBC
Java Data Base Connectivity:Java數據庫連接。是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。根本上說JDBC是一種規范,它提供的接口,一套完整的,允許便捷式訪問底層數據庫。
簡單而言,JDBC就是Java執行SQL語句進行數據庫操作的API。
不同的數據庫都有其自己的Driver驅動程序,為了便于開發者使用,Sun公司出手了:制定JDBC規范,統一了標準。
- JDBC無需單獨導包,包含在Java SE里
版本歷程
在JDK 1.0時JDBC只是個可選組件,到JDK 1.1開始成為了Java SE的一部分,也就是java.sql類包。所以:JDBC 1.0是隨著JDK 1.1一起發布的。
總的來講,JDBC發展到4.0版本就已經非常完善了,使用起來非常的方便。
生存現狀
雖然NoSQL如日中天,但傳統的RDBMS不可或缺,所以JDBC是必備的技能。
實現(框架)
無。
代碼示例
JDBC不同的版本代碼使用方式不盡相同,下面基于Java 8(也就是JDBC 4.2)來給個示例。所謂的JDBC四大步驟/四大參數,今天它來啦:
- /**
- * 在此處添加備注信息
- *
- * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a>
- * @site https://yourbatman.cn
- * @date 2021/10/6 21:20
- * @since 0.0.1
- */
- public class JDBCDemo {
- // ==================JDBC 四大參數 ======================
- public static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
- public static final String DB_URL = "jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC";
- public static final String DB_USER = "root";
- public static final String DB_PASS = "root";
- public static void main(String[] args) throws Exception {
- Class.forName(DB_DRIVER);
- try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
- PreparedStatement pstmt = conn.prepareStatement("SELECT id,name,age FROM user", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
- // ==============獲取到連接后,即可開始操作數據庫==================
- ResultSet rs = pstmt.executeQuery();
- //進行結果集滾動操作 打印結果集
- System.out.println("第二條數據:" + rs.getLong("id"));
- rs.absolute(1);
- System.out.println("第一條數據:" + rs.getLong("id"));
- rs.beforeFirst();
- System.out.println("最后一條數據:" + rs.getLong("id"));
- rs.afterLast();
- // 關閉結果集(應該在finally關閉)
- rs.close();
- }
- }
- }
這就是使用原生JDBC操作數據庫的簡單代碼示例。
工程源代碼:https://github.com/yourbatman/FXP-java-ee
總結
本文通過講解發展歷程、代碼示例分別介紹了兩項技術:
JavaMail:使用Java語言發送郵件(還可以接收郵件哦)
JDBC:Java操作數據庫的統一抽象層
這里多聊一句:大多數小伙伴可能覺得使用JDBC操作DB毫無意義,其實不然!筆者在面試候選人的時候問JDBC的內容還算比較高頻的,我的原因很簡單:它很重要,是理解MyBatis、Hibernate等框架的內核。另外,幾乎每個候選人簡歷里都會寫“對技術感興趣”,所以是否真的有“技術范”總得拉出來遛一遛吧!
本文轉載自微信公眾號「Java方向盤」