【方向盤(pán)】版本歷史&代碼示例之:JavaMail、JDBC
前言
若你還不太清楚Java EE是什么,可先移步這里:什么是Java EE?
發(fā)郵件是企業(yè)級(jí)應(yīng)用開(kāi)發(fā)的剛性需求,如:每晚定時(shí)任務(wù)跑完后自動(dòng)將結(jié)果數(shù)據(jù)發(fā)封郵件到領(lǐng)導(dǎo)郵箱供以查閱。郵件雖然“古老”,但相較于IM消息具有很多不可替代的優(yōu)勢(shì):
- 更為正式:相對(duì)重要的場(chǎng)合/數(shù)據(jù)用郵件更為合適
- 承載內(nèi)容多:一封郵件的文本字?jǐn)?shù)理論上無(wú)上限
- 格式豐富:可由附件、圖片、文本組合。支持HTML排版
- 發(fā)送形式豐富:除了收件人外,還可以抄送、密送
既然發(fā)郵件的場(chǎng)景這么常見(jiàn),但據(jù)我經(jīng)驗(yàn),每每遇到發(fā)郵件問(wèn)題時(shí),同事往往“頭疼不已”,你是否也有類(lèi)似情況呢?本文就來(lái)聊聊JavaMail的發(fā)展歷程,然后給出一些代碼示例。
除此之外,本文還會(huì)聊聊更為重要的JDBC,它高頻的出現(xiàn)在各大面試場(chǎng)合里,是考驗(yàn)一個(gè)求職者技術(shù)基礎(chǔ)水平的重要知識(shí)點(diǎn),更是流行框架MyBatis的基石。
所屬專(zhuān)欄
【方向盤(pán)】-Java EE
相關(guān)下載
- 【本專(zhuān)欄源代碼】:https://github.com/yourbatman/FXP-java-ee
- 【女?huà)zKnife-Initializr工程】訪問(wèn)地址:http://152.136.106.14:8761
- 【程序員專(zhuān)用網(wǎng)盤(pán)】公益上線啦,注冊(cè)送1G超小容量,幫你實(shí)踐做減法:https://wangpan.yourbatman.cn
- 【Java開(kāi)發(fā)軟件包(Mac)】:https://wangpan.yourbatman.cn/s/rEH0 提取碼:javakit
版本約定
- Java EE:6、7、8
- Jakarta EE:8、9、9.1
正文
JavaMail
JavaMail API提供了一個(gè)獨(dú)立于平臺(tái)和協(xié)議的框架來(lái)構(gòu)建郵件和消息傳遞應(yīng)用程序。JavaMail API作為可選包提供,可與Java SE平臺(tái)一起使用,也包含在JavaEE平臺(tái)中。
JavaMail 是sun公司為方便Java開(kāi)發(fā)人員在應(yīng)用程序中實(shí)現(xiàn)郵件發(fā)送和接收功能而提供的一套標(biāo)準(zhǔn)開(kāi)發(fā)包,它支持一些常用的郵件協(xié)議,如SMTP,POP3,IMAP,還有MIME(發(fā)送附件)等。我們?cè)谑褂肑avaMail API 編寫(xiě)郵件時(shí),無(wú)須考慮郵件的底層實(shí)現(xiàn)細(xì)節(jié),只要調(diào)用JavaMail 開(kāi)發(fā)包中相應(yīng)的API類(lèi)就可以了。
- <!-- 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> <!-- 對(duì)應(yīng)的參考實(shí)現(xiàn)為:com.sun.mail:jakarta.mail -->
- <!-- <version>1.6.7</version> 此版本命名空間同javax -->
- </dependency>
版本歷程
JavaMail的最新版本是1.6.2,于2018.08發(fā)布。
javax.mail-api.jar是JavaMail的API,一般無(wú)需單獨(dú)引入。即使需要引入,scope使用provide即可。com.sun.mail:javax.mail.jar是JavaMail的參考實(shí)現(xiàn),包括SMTP、IMAP和POP3等常見(jiàn)協(xié)議的實(shí)現(xiàn)。
說(shuō)明:“自古”傳出的發(fā)郵件需要導(dǎo)入兩個(gè)jar包,中的activtion.jar不是必須的,一個(gè)mail.jar大部分情況下就夠了
值得注意的是:借助Spring發(fā)送郵件,并沒(méi)有spring-mail獨(dú)立模塊(相關(guān)類(lèi)在spring-context-support這個(gè)模塊里),只有Spring Boot提供的spring-boot-starter-mail獨(dú)立啟動(dòng)器。
生存現(xiàn)狀
不可或缺,且已非常成熟。
實(shí)現(xiàn)(框架)
com.sun.mail:javax.mail或者com.sun.mail:jakarta.mail即為官方參考實(shí)現(xiàn),Spring Boot也是使用它來(lái)發(fā)送郵件的。
代碼示例
生產(chǎn)環(huán)境當(dāng)然建議使用Spring(or Spring Boot)提供的mail能力來(lái)發(fā)送郵件,非常簡(jiǎn)單方便。本文加點(diǎn)料,直接使用底層API來(lái)試試。
JavaMail API 按照功能可以劃分為如下三大類(lèi):
- 創(chuàng)建和解析郵件的API
- 發(fā)送郵件的API
- 接收郵件的API
這三大類(lèi)涉及到很多類(lèi),但核心的只有4個(gè),也就是俗稱(chēng)的JavaMail四大核心類(lèi)。如下圖所示:
絕大部分情況下,我們只需使用JavaMail發(fā)送郵件即可,也就是三個(gè)類(lèi):
- Session:用于定義整個(gè)應(yīng)用程序所需的環(huán)境信息。如主機(jī)名、端口、郵件協(xié)議等等
- Message:郵件內(nèi)容。通常使用它的子類(lèi)javax.mail.internet.MimeMessage 類(lèi)。還有如SMTPMessage、SMTPMessage等等
- Transport:發(fā)送郵件的核心API 類(lèi)
下面筆者使用JavaMail API發(fā)送一封郵件到自己的郵箱:yourbatman@aliyun.com,代碼如下。
準(zhǔn)備基礎(chǔ)發(fā)送、接收人元信息:
- // =====發(fā)送者信息======
- 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郵箱這里使用授權(quán)碼登錄,而不是密碼哦
- public static final String SENDER_QQ_SMTP_SERVER = "smtp.qq.com";
- // =====收件人信息======
- public static final String RECIPIENT_ADDRESS = "yourbatman@aliyun.com";
什么是QQ郵箱登錄授權(quán)碼?就是這個(gè)東東(具體怎么獲得,自己用谷歌百度一下):
調(diào)用API,書(shū)寫(xiě)發(fā)送郵件的代碼:
- /**
- * 發(fā)送郵件
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- Properties props = new Properties();
- props.setProperty("mail.smtp.auth", "true"); //用戶的認(rèn)證方式
- props.setProperty("mail.transport.protocol", "smtp"); // 傳輸協(xié)議
- props.setProperty("mail.smtp.host", SENDER_QQ_SMTP_SERVER); // 發(fā)件人的SMTP服務(wù)器地址
- Session session = Session.getInstance(props);
- session.setDebug(true); // 在控制臺(tái)打印調(diào)試信息
- // ======創(chuàng)建一封郵件======
- Message msg = createMimeMessage(session);
- // ======準(zhǔn)備發(fā)送======
- Transport transport = session.getTransport();
- transport.connect(SENDER_ACCOUNT, SENDER_PASSWORD);
- transport.sendMessage(msg, msg.getAllRecipients()); // 發(fā)送郵件(包括)
- //如果只想發(fā)送給指定的人,可以如下寫(xiě)法
- //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)); // 設(shè)置發(fā)件人地址
- /**
- * 設(shè)置收件人地址(可以增加多個(gè)收件人、抄送、密送),即下面這一行代碼書(shū)寫(xiě)多行
- * MimeMessage.RecipientType.TO:發(fā)送
- * MimeMessage.RecipientType.CC:抄送
- * MimeMessage.RecipientType.BCC:密送
- */
- msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(RECIPIENT_ADDRESS));
- msg.setSubject("我是郵件主題", "UTF-8");
- msg.setContent("我是簡(jiǎn)單的純文本郵件!", "text/html;charset=UTF-8");
- msg.setSentDate(new Date()); // 郵件的發(fā)送時(shí)間,默認(rèn)立即發(fā)送
- return msg;
- }
運(yùn)行程序,收到郵件,完美!
控制臺(tái)的debug日志可以窺探這個(gè)發(fā)送過(guò)程:
- 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
本專(zhuān)欄源代碼:https://github.com/yourbatman/FXP-java-ee
JDBC
Java Data Base Connectivity:Java數(shù)據(jù)庫(kù)連接。是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供統(tǒng)一訪問(wèn),它由一組用Java語(yǔ)言編寫(xiě)的類(lèi)和接口組成。根本上說(shuō)JDBC是一種規(guī)范,它提供的接口,一套完整的,允許便捷式訪問(wèn)底層數(shù)據(jù)庫(kù)。
簡(jiǎn)單而言,JDBC就是Java執(zhí)行SQL語(yǔ)句進(jìn)行數(shù)據(jù)庫(kù)操作的API。
不同的數(shù)據(jù)庫(kù)都有其自己的Driver驅(qū)動(dòng)程序,為了便于開(kāi)發(fā)者使用,Sun公司出手了:制定JDBC規(guī)范,統(tǒng)一了標(biāo)準(zhǔn)。
- JDBC無(wú)需單獨(dú)導(dǎo)包,包含在Java SE里
版本歷程
在JDK 1.0時(shí)JDBC只是個(gè)可選組件,到JDK 1.1開(kāi)始成為了Java SE的一部分,也就是java.sql類(lèi)包。所以:JDBC 1.0是隨著JDK 1.1一起發(fā)布的。
總的來(lái)講,JDBC發(fā)展到4.0版本就已經(jīng)非常完善了,使用起來(lái)非常的方便。
生存現(xiàn)狀
雖然NoSQL如日中天,但傳統(tǒng)的RDBMS不可或缺,所以JDBC是必備的技能。
實(shí)現(xiàn)(框架)
無(wú)。
代碼示例
JDBC不同的版本代碼使用方式不盡相同,下面基于Java 8(也就是JDBC 4.2)來(lái)給個(gè)示例。所謂的JDBC四大步驟/四大參數(shù),今天它來(lái)啦:
- /**
- * 在此處添加備注信息
- *
- * @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 四大參數(shù) ======================
- 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)) {
- // ==============獲取到連接后,即可開(kāi)始操作數(shù)據(jù)庫(kù)==================
- ResultSet rs = pstmt.executeQuery();
- //進(jìn)行結(jié)果集滾動(dòng)操作 打印結(jié)果集
- System.out.println("第二條數(shù)據(jù):" + rs.getLong("id"));
- rs.absolute(1);
- System.out.println("第一條數(shù)據(jù):" + rs.getLong("id"));
- rs.beforeFirst();
- System.out.println("最后一條數(shù)據(jù):" + rs.getLong("id"));
- rs.afterLast();
- // 關(guān)閉結(jié)果集(應(yīng)該在finally關(guān)閉)
- rs.close();
- }
- }
- }
這就是使用原生JDBC操作數(shù)據(jù)庫(kù)的簡(jiǎn)單代碼示例。
工程源代碼:https://github.com/yourbatman/FXP-java-ee
總結(jié)
本文通過(guò)講解發(fā)展歷程、代碼示例分別介紹了兩項(xiàng)技術(shù):
JavaMail:使用Java語(yǔ)言發(fā)送郵件(還可以接收郵件哦)
JDBC:Java操作數(shù)據(jù)庫(kù)的統(tǒng)一抽象層
這里多聊一句:大多數(shù)小伙伴可能覺(jué)得使用JDBC操作DB毫無(wú)意義,其實(shí)不然!筆者在面試候選人的時(shí)候問(wèn)JDBC的內(nèi)容還算比較高頻的,我的原因很簡(jiǎn)單:它很重要,是理解MyBatis、Hibernate等框架的內(nèi)核。另外,幾乎每個(gè)候選人簡(jiǎn)歷里都會(huì)寫(xiě)“對(duì)技術(shù)感興趣”,所以是否真的有“技術(shù)范”總得拉出來(lái)遛一遛吧!
本文轉(zhuǎn)載自微信公眾號(hào)「Java方向盤(pán)」