[英]Is it ok for a method to call itself again after catching an exception?
我正在運行后台作業,每天早晨7:00,調用一種方法以將電子郵件發送到特定地址,為此我正在使用Java郵件。 我之所以這樣問,是因為有時它會發送MessagingException
(總是在發生此異常的情況下)。 這是錯誤:
nested exception is:
class javax.mail.MessagingException: 530 5.7.1 Client was not authenticated
正如我所說,它只是不時發生; 但這有點煩人,因為我必須確保手動發送郵件以防失敗。 我沒有找到發生這種情況的原因,我嘗試查找此消息,一些答案表明這是服務器出現問題; 不幸的是,我無法控制它。 當我手動執行例程時,有時最多需要5或7次嘗試才能發送郵件。
因此,我想做的是在catch部分中調用相同的方法,而且我還放置了一個計數器來控制嘗試次數,以防萬一異常被捕獲超過5次。
您會建議這種方法嗎? 感謝您的幫助和解答。
這是我每次拋出MessagingException時都試圖重新調用的方法的代碼:
public void sendMail(String msj, String dest, String asunto, File attachmentSource, int count) {
String to = dest;
String from = "some.user@vw.com.mx";
String host = "someserver.xx.xx.xx";
boolean debug = true;
Properties props = new Properties();
props.put("mail.smtp.host", host);
if (debug) {
props.put("mail.debug", "");
}
Session session = Session.getInstance(props, null);
session.setDebug(debug);
try {
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("Reporte");
msg.setSentDate(new Date());
msg.setText(msj);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(new FileDataSource(attachmentSource)));
messageBodyPart.setFileName(attachmentSource.getName());
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
msg.setContent(multipart);
Transport.send(msg);
} catch (MessagingException mex) {
Logger.getLogger(SendMSG.class.getName()).log(Level.SEVERE, ("ERROR EN ENVÍO!!!! " + mex.getMessage()));
//THIS IS a TEST TO TRY UNTIL THE MSG IS SENT
count++;
if (count <= 5) {
Logger.getLogger(SendMSG.class.getName()).log(Level.INFO, ("Intento No: " + count + " de 5" + mex.getMessage()));
sendMail(msj, dest, asunto, attachmentSource, count);
} else {
Logger.getLogger(SendMSG.class.getName()).log(Level.SEVERE, ("No. de Intentos excedido " + count + " SALIR DE MÉTODO" + mex.getMessage()));
}
mex.printStackTrace();
}
}
您的解決方案很好,但是很混亂。 我將重試和發送分開。
public boolean sendMail(String msj, String dest, String asunto, File attachmentSource, int retries) {
for (int i = 0; i< retries; i++){
if (sendMail(msj, dest, asunto, attachmentSource)){
return true;
}
}
return false;
}
public boolean sendMail(String msj, String dest, String asunto, File attachmentSource) {
try {
...
return true;
} catch (Exception ex) {
return false;
}
}
它的作用與代碼基本相同,但是提高了可讀性。
想想一種將兩件事分開的方法:執行方法的主要邏輯和發生故障時的行為。 如果可以編寫一個接口,則可以使用ExceptionHandler
類型,在其中聲明方法handleFault
(例如)。 然后,在您的主類中,您可以注入ExceptionHandler
某些特定實現,您可以在其中確定發生故障時的處理方式。
這將使測試變得更加容易,因為您可以從一個簡單的測試對象中替換“實時”或“生產”或我們所謂的行為,在這里您只想檢查是否處理了錯誤的案例。
我認為,值得一提的是馬丁·福勒(Martin Fowler)在此處描述的電路斷路器模式 : https : //martinfowler.com/bliki/CircuitBreaker.html
您可以使用單獨的策略來處理錯誤,重試模板(重試次數,兩次重試之間的時間等)。
我想假設錯誤取決於時間。 由於它有時會發生,而有時卻不會。 考慮到這一點,我建議在count++
之后將wait()放入循環中
像這樣:
synchronized (this)
{
this.wait(count*1000);//delay after each error
}
其他答案中有一些有用的建議,但我認為問題的核心在於您永遠不會向服務器進行身份驗證。 除非您使用不需要身份驗證的本地服務器,否則我不知道它是如何工作的。
如JavaMail常見問題解答中所述,將您的Transport.send調用替換為
Transport.send(msg, username, password);
用戶名和密碼是登錄到郵件服務器的憑據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.