spring boot定時(shí)任務(wù)接收郵件并且存儲(chǔ)附件的方法講解
在spring boot中寫定時(shí)任務(wù)很簡單,兩個(gè)注解就可以實(shí)現(xiàn)。在啟動(dòng)類中加@EnableScheduling ,然后在你需要定時(shí)的方法上加上@Scheduled(cron="0 10 8 * * ?");括號(hào)內(nèi)為cron表達(dá)式。如下圖:


接收郵件及其判斷是否有附件,并且存儲(chǔ)附件。
public class TimerTaskServiceImpl implements TimerTaskService {
@Autowired
private ParseTxtServiceImpl parseTxtService;
/**
* 接收郵件
*/
@Override
@Scheduled(cron="0 10 8 * * ?")
public void timerTaskInfo(){
//郵件配置信息
String host=Constants.MAIL_HOST;
String userName=Constants.MAIL_USER_NAME;
String passWord=Constants.MAIL_PASS_WORD;
//郵件配置類
Properties properties=new Properties();
//郵件配置緩存
Session session=Session.getDefaultInstance(properties);
session.setDebug(true);
String fileName=null;
try {
//郵件服務(wù)器的類型
Store store = session.getStore("pop3");
//連接郵箱服務(wù)器
store.connect(host,userName,passWord);
// 獲得用戶的郵件帳戶
Folder folder=store.getFolder("INBOX");
if (folder == null) {
logger.info("獲取郵箱文件信息為空");
}
// 設(shè)置對(duì)郵件帳戶的訪問權(quán)限可以讀寫
folder.open(Folder.READ_WRITE);
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.DATE,-1);
Date mondayDate = calendar.getTime();
SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.GT, mondayDate);
SearchTerm address=new SubjectTerm( "MU Report");
SearchTerm comparisonAndTerm = new AndTerm(address, comparisonTermLe);
Message[] messages = folder.search(comparisonAndTerm);
for(int i = 0 ; i < messages.length ; i++){
MimeMessage msg = (MimeMessage) messages[i];
//判斷是否有附件
boolean isContainerAttachment = isContainAttachment(msg);
if (isContainerAttachment) {
//保存附件
fileName=saveAttachment(msg,Constants.STORAGE_FILE);
//保存接收到的郵件并且收件箱刪除郵件
msg.setFlag(Flags.Flag.DELETED, true);
}
if(!isContainerAttachment) {
continue;
}
}
folder.close(true);
store.close();
parseTxtService.readTxt(fileName);
}catch (NoSuchProviderException e){
loggerError.error("接收郵箱信息異常:{}",e);
}catch (MessagingException e){
loggerError.error("連接郵箱服務(wù)器信息異常:{}",e);
}catch (IOException e){
loggerError.error("接收郵箱信息解析異常:{}",e);
}catch (IllegalStateException e){
loggerError.error("接收郵箱信息為空:{}",e);
}
}
/**
* 判斷郵件中是否包含附件
* @return 郵件中存在附件返回true,不存在返回false
* @throws MessagingException
* @throws IOException
*/
public static boolean isContainAttachment(Part part) throws MessagingException, IOException {
boolean flag = false;
if (part.isMimeType(Constants.MULTI_PART)) {
MimeMultipart multipart = (MimeMultipart) part.getContent();
int partCount = multipart.getCount();
for (int i = 0; i < partCount; i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
String disp = bodyPart.getDisposition();
if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) ||
disp.equalsIgnoreCase(Part.INLINE))) {
flag = true;
} else if (bodyPart.isMimeType(Constants.MULTI_PART)) {
flag = isContainAttachment(bodyPart);
} else {
String contentType = bodyPart.getContentType();
if (contentType.indexOf(Constants.APPLICATION_CONTEXT) != -1) {
flag = true;
}
if (contentType.indexOf(Constants.NAME_CONTEXT) != -1) {
flag = true;
}
}
if (flag){
break;
}
}
} else if (part.isMimeType(Constants.MESSAGE_RFC)) {
flag = isContainAttachment((Part)part.getContent());
}
return flag;
}
/**
* 保存附件
* @param part 郵件中多個(gè)組合體中的其中一個(gè)組合體
* @param destDir 附件保存目錄
* @throws UnsupportedEncodingException
* @throws MessagingException
* @throws FileNotFoundException
* @throws IOException
*/
public String saveAttachment(Part part, String destDir) throws UnsupportedEncodingException,
MessagingException, FileNotFoundException, IOException {
String fileName=null;
if (part.isMimeType(Constants.MULTI_PART)) {
Multipart multipart = (Multipart) part.getContent(); //復(fù)雜體郵件
//復(fù)雜體郵件包含多個(gè)郵件體
int partCount = multipart.getCount();
for (int i = 0; i < partCount; i++) {
//獲得復(fù)雜體郵件中其中一個(gè)郵件體
BodyPart bodyPart = multipart.getBodyPart(i);
//某一個(gè)郵件體也有可能是由多個(gè)郵件體組成的復(fù)雜體
String disp = bodyPart.getDisposition();
if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase
(Part.INLINE))) {
InputStream is = bodyPart.getInputStream();
saveFile(is, destDir, decodeText(bodyPart.getFileName()));
fileName=decodeText(bodyPart.getFileName());
} else if (bodyPart.isMimeType(Constants.MULTI_PART)) {
saveAttachment(bodyPart,destDir);
} else {
String contentType = bodyPart.getContentType();
if (contentType.indexOf(Constants.NAME_CONTEXT) != -1 || contentType.indexOf
(Constants.APPLICATION_CONTEXT) != -1) {
saveFile(bodyPart.getInputStream(), destDir, decodeText(bodyPart.getFileName()));
fileName=decodeText(bodyPart.getFileName());
}
}
}
} else if (part.isMimeType(Constants.MESSAGE_RFC)) {
saveAttachment((Part) part.getContent(),destDir);
}
return fileName;
}
/**
* 讀取輸入流中的數(shù)據(jù)保存至指定目錄
* @param is 輸入流
* @param fileName 文件名
* @param destDir 文件存儲(chǔ)目錄
* @throws FileNotFoundException
* @throws IOException
*/
private void saveFile(InputStream is, String destDir, String fileName)
throws FileNotFoundException, IOException {
BufferedInputStream bis = new BufferedInputStream(is);
if(fileName.contains(Constants.TXT_SUFIXX)) {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(new File(destDir + fileName)));
int len = -1;
while ((len = bis.read()) != -1) {
bos.write(len);
bos.flush();
}
bos.close();
bis.close();
}
}
}
其中查詢郵件的條件,你可以自行更改。

接收郵件服務(wù)器的配置

可能出現(xiàn)的bug
說說用模板可能會(huì)碰到的bug。
怎么回事呢?代碼寫了,看了好幾遍也沒錯(cuò),就是運(yùn)行就報(bào)錯(cuò),在網(wǎng)上看了別人的代碼拿過來還是報(bào)錯(cuò),報(bào)錯(cuò)如下:

這個(gè)錯(cuò)誤大概意思就是我的模板的html中每個(gè)標(biāo)簽都要是閉標(biāo)簽,要這種類型的<a></a>,假如是<img xxx>這種標(biāo)簽就會(huì)報(bào)錯(cuò)。
如下所示,最坑的方法就是修改的,而且以后html的標(biāo)簽都要是一對(duì)一對(duì)的,坑啊、

后來有找了很多資料,原來發(fā)現(xiàn)是這里,themeleaf默認(rèn)應(yīng)該是2.xx版本,這個(gè)版本解析標(biāo)簽都要是一對(duì)一對(duì)的,到了3.xx之后,就不需要這么麻煩了!

都是版本問題
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
- spring中通過ApplicationContext getBean獲取注入對(duì)象的方法實(shí)例
- Springboot-dubbo-fescar 阿里分布式事務(wù)的實(shí)現(xiàn)方法
- 詳解spring-boot下如何滿足多生產(chǎn)環(huán)境中個(gè)性化定制功能
- Spring 中優(yōu)雅的獲取泛型信息的方法
- spring @Transactional 無效的解決方案
- activemq整合springboot使用方法(個(gè)人微信小程序用)
- Springboot項(xiàng)目打war包docker包找不到resource下靜態(tài)資源的解決方案
- Spring自帶的校驗(yàn)框架Validation的使用實(shí)例
- 詳解Spring框架下向異步線程傳遞HttpServletRequest參數(shù)的坑
- Spring通過ApplicationContext主動(dòng)獲取bean的方法講解
相關(guān)文章
Java8中Lambda表達(dá)式的理解與應(yīng)用
Java8最值得學(xué)習(xí)的特性就是Lambda表達(dá)式和Stream?API,如果有python或者javascript的語言基礎(chǔ),對(duì)理解Lambda表達(dá)式有很大幫助,下面這篇文章主要給大家介紹了關(guān)于Java8中Lambda表達(dá)式的相關(guān)資料,需要的朋友可以參考下2022-02-02
mybatis-plus返回map自動(dòng)轉(zhuǎn)駝峰配置操作
這篇文章主要介紹了mybatis-plus返回map自動(dòng)轉(zhuǎn)駝峰配置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11
SpringCloud_Sleuth分布式鏈路請(qǐng)求跟蹤的示例代碼
Spring Cloud Sleuth是一款針對(duì)Spring Cloud的分布式跟蹤工具,本文通過實(shí)例代碼介紹了SpringCloud_Sleuth分布式鏈路請(qǐng)求跟蹤,感興趣的朋友跟隨小編一起看看吧2023-02-02
java文件操作練習(xí)代碼 讀取某個(gè)盤符下的文件
這篇文章主要介紹了java讀取某個(gè)盤符下的文件示例,代碼中要求的是絕對(duì)路徑,編譯過程中要注意絕對(duì)路徑問題和異常的抓取2014-01-01
springboot對(duì)象為null的屬性在json中不顯示的解決
這篇文章主要介紹了springboot對(duì)象為null的屬性在json中不顯示的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
SpringBoot 集成JUnit5的詳細(xì)操作過程
JUnit5是最新的Java單元測(cè)試框架,提供了靈活的測(cè)試支持,它由JUnit Platform、JUnit Jupiter和JUnit Vintage組成,支持不同環(huán)境下的測(cè)試運(yùn)行,SpringBoot從2.2版本開始默認(rèn)支持JUnit5,本文介紹了SpringBoot 集成JUnit5的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2024-10-10
Java實(shí)現(xiàn)京東聯(lián)盟API數(shù)據(jù)獲取功能
這篇文章介紹了Java獲取京東聯(lián)盟API數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
Intellij?IDEA創(chuàng)建web項(xiàng)目的超詳細(xì)步驟記錄
如果剛開始接觸IDEA,或者之前使用的是eclipse/myEclipse的話,即使是創(chuàng)建一個(gè)JAVA WEB項(xiàng)目,估計(jì)也讓很多人費(fèi)了好幾個(gè)小時(shí),下面這篇文章主要給大家介紹了關(guān)于Intellij?IDEA創(chuàng)建web項(xiàng)目的超詳細(xì)步驟,需要的朋友可以參考下2022-08-08

