spring boot定時(shí)任務(wù)接收郵件并且存儲(chǔ)附件的方法講解
在spring boot中寫定時(shí)任務(wù)很簡(jiǎn)單,兩個(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ì)郵件帳戶的訪問(wèn)權(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
說(shuō)說(shuō)用模板可能會(huì)碰到的bug。
怎么回事呢?代碼寫了,看了好幾遍也沒(méi)錯(cuò),就是運(yùn)行就報(bào)錯(cuò),在網(wǎng)上看了別人的代碼拿過(guò)來(lái)還是報(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ì)的,坑啊、
后來(lái)有找了很多資料,原來(lái)發(fā)現(xiàn)是這里,themeleaf默認(rèn)應(yīng)該是2.xx版本,這個(gè)版本解析標(biāo)簽都要是一對(duì)一對(duì)的,到了3.xx之后,就不需要這么麻煩了!
都是版本問(wèn)題
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
- spring中通過(guò)ApplicationContext getBean獲取注入對(duì)象的方法實(shí)例
- Springboot-dubbo-fescar 阿里分布式事務(wù)的實(shí)現(xiàn)方法
- 詳解spring-boot下如何滿足多生產(chǎn)環(huán)境中個(gè)性化定制功能
- Spring 中優(yōu)雅的獲取泛型信息的方法
- spring @Transactional 無(wú)效的解決方案
- activemq整合springboot使用方法(個(gè)人微信小程序用)
- Springboot項(xiàng)目打war包docker包找不到resource下靜態(tài)資源的解決方案
- Spring自帶的校驗(yàn)框架Validation的使用實(shí)例
- 詳解Spring框架下向異步線程傳遞HttpServletRequest參數(shù)的坑
- Spring通過(guò)ApplicationContext主動(dòng)獲取bean的方法講解
相關(guān)文章
阿里nacos+springboot+dubbo2.7.3統(tǒng)一處理異常的兩種方式
本文主要介紹了阿里nacos+springboot+dubbo2.7.3統(tǒng)一處理異常的兩種方式,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03springboot的application.yml配置port不生效的解決方案
這篇文章主要介紹了springboot的application.yml配置port不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Java thread.isInterrupted() 返回值不確定結(jié)果分析解決
這篇文章主要介紹了Java thread.isInterrupted() 返回值不確定結(jié)果分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12JAVA實(shí)現(xiàn)單例模式的四種方法和一些特點(diǎn)
JAVA實(shí)現(xiàn)單例模式的四種方法和一些特點(diǎn),需要的朋友可以參考一下2013-03-03