java郵件發送和短信發送(二)

上次介紹了基於Velocity模板java郵件發送,這次我們對程序做了一次重構,實現的是根據相應的請求發送郵件或者短信。

   首先我們來定義一個頂層消息接口:

   

  1. /**  
  2.  * 功能:  系統消息發送服務 <p>  
  3.  * 用法: 
  4.  * @version 1.0 
  5.  */   
  6. public interface MessageService {  
  7.       
  8. /** 
  9.  * 根據消息模板表中的消息編號取得消息模板,填充,發送 
  10.  *  
  11.  * @param bmtCode  消息模板表中的消息編號 
  12.  * @param params 填充模板內容的參數 
  13.  * @param to  消息的接收人 
  14.  * @throws CheckException 模板不存在,或是發送消息出現異常 
  15.  */  
  16. public void sendMessage(String bmtCode,Map params, String... to) throws CheckException;  
  17.   
  18. }  

 

    接着我們實現該接口:

   

  1. public class MessageServiceImpl implements MessageService{  
  2.     /** 
  3.      * Logger for this class 
  4.      */  
  5.     private static final Logger logger = Logger.getLogger(MessageServiceImpl.class);  
  6.   
  7.    @Autowired  
  8.     private BaseMessageTempletDAO baseMessageTempletDAO;  
  9.      
  10.    @Autowired  
  11.     private SenderFactory senderFactory;  
  12.       
  13.     @Override  
  14.     public void sendMessage(String bmtCode, Map params, String... to)  
  15.             throws CheckException {  
  16.         // 檢查參數   
  17.         if (StringUtils.isEmpty(bmtCode) || ArrayUtils.isEmpty(to)){  
  18.             throw new CheckException("模板編號不能爲空,或消息的接收人不能爲空");  
  19.         }  
  20.           
  21.         // 從數據庫取出模板   
  22.         BaseMessageTempletEO queryParam = new BaseMessageTempletEO();  
  23.         queryParam.setBmtCode(bmtCode);   
  24.           
  25.         BaseMessageTempletEO template = null;  
  26.         try {  
  27.             template = baseMessageTempletDAO.selectEOByEO(queryParam);  
  28.         } catch (Exception e) {  
  29.             // 查詢失敗   
  30.             logger.error("查詢模板:" + bmtCode + " 時發生異常", e);  
  31.             throw new CheckException(e);  
  32.         }  
  33.         // 檢查模板是否存在   
  34.         if (template == null){  
  35.             logger.info("編號爲: "  + bmtCode + " 的消息模板不存在.");  
  36.             throw new CheckException("編號爲: "  + bmtCode + " 的消息模板不存在.");  
  37.         }  
  38.           
  39.         // 檢查消息類型   
  40.         String msgType = template.getBmtType();  
  41.         if (StringUtils.isEmpty(msgType)){  
  42.             logger.info("編號爲: "  + bmtCode + " 的消息模板消息類型未知.");  
  43.             throw new CheckException("編號爲: "  + bmtCode + " 的消息模板消息類型未知,無法發送.");  
  44.         }  
  45.           
  46.           
  47.         // 解析標題   
  48.         String title = null;  
  49.         if (StringUtils.isNotEmpty(template.getBmtTitle()) && params != null){  
  50.             try {  
  51.                 title = VelocityParserUtil.getInstance().parseVelocityTemplate(template.getBmtTitle(),params);  
  52.             } catch (Exception e) {  
  53.                 logger.error("編號爲: "  + bmtCode + " 的消息模板解析 <標題 > 時失敗");  
  54.                 throw new CheckException(e);  
  55.             }  
  56.         }  
  57.         // 解析內容   
  58.         String content = null;  
  59.         if (StringUtils.isNotEmpty(template.getBmtContent()) && params != null){  
  60.             try {  
  61.                 content = VelocityParserUtil.getInstance().parseVelocityTemplate(template.getBmtContent(),params);  
  62.             } catch (Exception e) {  
  63.                 logger.error("編號爲: "  + bmtCode + " 的消息模板解析 <內容> 時失敗");  
  64.                 throw new CheckException(e);  
  65.             }  
  66.         }  
  67.           
  68.         // 發送   
  69.         Sender sender = senderFactory.getSender(msgType);  
  70.         if (sender == null){  
  71.             // 找不到對應類型的發送器   
  72.             logger.error("編號爲: "  + bmtCode + " 的消息模板,類型爲: " + msgType + " 沒有對應的消息發送器");  
  73.             throw new CheckException("編號爲: "  + bmtCode + " 的消息模板,類型爲: " + msgType + " 沒有對應的消息發送器");  
  74.         }  
  75.         sender.sender(title, content, to);  
  76.           
  77.           
  78.     }  
  79.   
  80. }  

 

  

 

    大家看到了代碼涉及到了DAO和Factory,這裏注入DAO是因爲我們把消息發送的相關信息都放進了數據庫存儲起來,我們根據識別號,去判斷髮送短息還是郵件,發送的模板是什麼等等。那我們寫一個發送消息的工廠類SendFactory:

   

  1. /** 
  2.  * 功能: 根據不同的消息類型,取得適應的消息發送器 
  3.  * <p> 
  4.  * 用法: 
  5.  *  
  6.  * @version 1.0 
  7.  */  
  8. public class SenderFactory {  
  9.     @Autowired  
  10.     @Qualifier("mailSenderAdapt")  
  11.     private Sender mailSender;  
  12.   
  13.     @Autowired  
  14.     @Qualifier("smsSenderAdapt")  
  15.     private Sender smsSender;  
  16.   
  17.     public Sender getSender(String type) {  
  18.         Sender sender = null;  
  19.         if (BaseMessageTempletEO.BMT_TYPE_MAIL.equalsIgnoreCase(type)) {  
  20.             // 郵件   
  21.             sender = mailSender;  
  22.         } else if (BaseMessageTempletEO.BMT_TYPE_SMS.equalsIgnoreCase(type)) {  
  23.             // 短信   
  24.             sender = smsSender;  
  25.         }  
  26.         return sender;  
  27.     }  
  28. }  

 

    如你所看到的我們會if的判斷得知該請求是要發送郵件還是發送短信。

    我們暫時放下前面的,定義一個頂層接口Sender:

   

  1. /**  
  2.  * 功能:   消息發送器接口<p>  
  3.  * 用法: 
  4.  * @version 1.0 
  5.  */   
  6. public interface Sender {  
  7.   
  8. /** 
  9.  * @param title 消息的標題 
  10.  * @param content 消息的內容 
  11.  * @param to 消息的接收人 
  12.  * @throws CheckException 
  13.  */  
  14.   
  15. public void sender(String title, String content, String... to) throws CheckException;  
  16.   
  17. }  

 

    然後我們要分別定義郵件和短信接口,並實現頂層接口Sender:

  

  1.  public class SmsSenderAdapt implements Sender {  
  2. @Autowired  
  3. @Qualifier("smsSenderImpl_commons")  
  4. private SmsSender smsSender;  
  5.   
  6. @Override  
  7. public void sender(String title, String content, String... to)  
  8.   throws CheckException {  
  9.  smsSender.sendSms(to, content);  
  10.   
  11. }  

 

   

  1. public class MailSenderAdapt implements Sender {  
  2.     @Autowired  
  3.     @Qualifier("emailSenderImpl_commons")  
  4.     private EmailSender emailSender;  
  5.       
  6.     @Autowired  
  7.     private ConfigService configService;  
  8.   
  9.     @Override  
  10.     public void sender(String title, String content, String... to)  
  11.             throws CheckException {  
  12.         // 從數據庫取發件人,及發件人姓名   
  13.         String from = configService.getConfig(BasePropertyID.MAIL_SMTP_FROM_ID);  
  14.         String fromName = configService.getConfig(BasePropertyID.MAIL_SMTP_FROMNAME_ID);  
  15.           
  16.         Mail mail = new Mail();  
  17.         mail.setFrom(from);  
  18.         mail.setFromName(fromName);  
  19.         mail.setTo(to);  
  20.         mail.setSubject(title);  
  21.         mail.setContent(content);  
  22.           
  23.         emailSender.sendEmail(mail);  
  24.   
  25.     }  
  26.   
  27. }  

 

    後面對sendEmail(mail)這個已經在上一篇實現了,大家可以返回去看一下,是不是明白了呢?

    接下來我詳細介紹發送短信的代碼。

    那好我們來時先剛剛短信的接口:

   

  1. /** 
  2.  * 功能: 短信發送服務 
  3.  * <p> 
  4.  * 用法: 
  5.  *  
  6.  * @version 1.0 
  7.  */  
  8.   
  9. public class SmsSenderImpl implements SmsSender,InitializingBean {  
  10.     /** 
  11.      * Logger for this class 
  12.      */  
  13.     private static final Logger logger = Logger.getLogger(SmsSenderImpl.class);  
  14.   
  15.     @Autowired  
  16.     private ConfigService configService;  
  17.       
  18.     private String smsUrl;  
  19.     private String cpidName;  
  20.     private String cpidValue;  
  21.     private String pwdName;  
  22.     private String pwdValue;  
  23.     private String pidName;  
  24.     private String pidValue;  
  25.     private String phoneName;  
  26.     private String msgName;  
  27.     private int maxLength = 60// 默認值   
  28.       
  29.     @Override  
  30.     public void sendSms(String mobilePhone, String message) throws CheckException {  
  31.         send(message, mobilePhone);  
  32.           
  33.     }  
  34.   
  35.     @Override  
  36.     public void sendSms(String[] mobilePhones, String message) throws CheckException {  
  37.         if (ArrayUtils.isEmpty(mobilePhones)){  
  38.             throw new CheckException("手機號碼不能爲空");  
  39.         }  
  40.         for (String phone : mobilePhones) {  
  41.             sendSms(phone, message);  
  42.         }  
  43.           
  44.     }  
  45.       
  46.   
  47.     /** 
  48.      * 如果超過短信的長度,則分成幾條發 
  49.      * @param content 
  50.      * @param phoneNo 
  51.      * @return 
  52.      * @throws CheckException 
  53.      */  
  54.     private String send(String content,String phoneNo) throws CheckException{  
  55.         content = StringUtils.trimToEmpty(content);  
  56.         phoneNo = StringUtils.trimToEmpty(phoneNo);  
  57.           
  58.         if (StringUtils.isEmpty(content)){  
  59.             throw new CheckException("短信內容爲空");  
  60.         }  
  61.         if (StringUtils.isEmpty(phoneNo)){  
  62.             throw new CheckException("手機號爲空");  
  63.         }  
  64.         // 如果服務未準備好,先初始化   
  65.         if (!isReady()) {  
  66.             try {  
  67.                 init();  
  68.                 // 初始化後,服務仍未準備好   
  69.                 if (!isReady()) {  
  70.                     throw new CheckException("郵件服務初始化異常");  
  71.                 }  
  72.             } catch (Exception e) {  
  73.                 logger.error("send(String, String)", e);  
  74.                   
  75.                 throw new CheckException("郵件服務初始化異常");  
  76.             }  
  77.         }  
  78.           
  79.         // 如果超過最大長度,則分成幾條發送   
  80.         int count = content.length() / maxLength;  
  81.         int reminder = content.length() % maxLength;  
  82.            
  83.         if (reminder != 0 ){  
  84.            count += 1;  
  85.         }  
  86.         StringBuffer result = new StringBuffer();  
  87.         int i = 0;  
  88.         while (count > i){  
  89.            result.append(doSend(StringUtils.substring(content, i*maxLength, (i+1)*maxLength),phoneNo));  
  90.            result.append(";");  
  91.            i ++;  
  92.         }  
  93.         return result.toString();  
  94.     }  
  95.       
  96.     private boolean isReady(){  
  97.         return !(smsUrl == null || cpidName == null || cpidValue == null  
  98.                 || pwdName == null || pwdValue == null || pidName == null  
  99.                 || pidValue == null || phoneName == null || msgName == null || maxLength <= 0);  
  100.     }  
  101.     /** 
  102.      * @param content 
  103.      * @param phoneNo 
  104.      * @return 
  105.      * @throws CheckException 
  106.      */  
  107.     private String doSend(String content,String phoneNo) throws CheckException{  
  108.           
  109.         // 使用httpclient模擬http請求   
  110.         HttpClient client = new HttpClient();  
  111.         // 設置參數編碼   
  112.         client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "GBK");  
  113.           
  114.         PostMethod method = new PostMethod(smsUrl);  
  115.           
  116.         method.addParameter(cpidName, cpidValue);  
  117.         method.addParameter(pidName, pidValue);  
  118.         method.addParameter(pwdName, pwdValue);  
  119.         method.addParameter(phoneName, phoneNo);  
  120.         method.addParameter(msgName, content);  
  121.           
  122.           
  123.         BufferedReader br = null;  
  124.         String reponse  = null;  
  125.         try {  
  126.             int returnCode = client.executeMethod(method);  
  127.   
  128.             if (returnCode != HttpStatus.SC_OK) {  
  129.                 // 請求出錯   
  130.                 throw new CheckException("短信接口異常");  
  131.   
  132.             }  
  133.             br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));  
  134.             reponse = br.readLine();  
  135.             String responseCode = StringUtils.substring(reponse, 01);  
  136.             if (!"0".equals(responseCode)){  
  137.                 throw new CheckException(getResponseMsg(responseCode));  
  138.             }  
  139.   
  140.         } catch (Exception e) {  
  141.             logger.error("doSend(String, String)", e);  
  142.   
  143.             if (e instanceof CheckException){  
  144.                 throw (CheckException)e;  
  145.             }else{  
  146.                 throw new CheckException("未知異常"); // 未知異常   
  147.             }  
  148.         } finally {  
  149.             method.releaseConnection();  
  150.             if (br != null)  
  151.                 try {  
  152.                     br.close();  
  153.                 } catch (Exception e1) {  
  154.                     logger.error("doSend(String, String)", e1);  
  155.   
  156.                     e1.printStackTrace();  
  157.                 }  
  158.         }  
  159.   
  160.         return reponse;  
  161.     }  
  162.   
  163.     public void afterPropertiesSet() throws Exception {  
  164.         // 初始化   
  165.         init();  
  166.     }  
  167.       
  168.     private void init() throws Exception{  
  169.           
  170.         smsUrl = configService.getConfig(BasePropertyID.SMS_URL_ID);  
  171.         cpidName = configService.getConfig(BasePropertyID.SMS_CPID_NAME_ID);  
  172.         cpidValue = configService.getConfig(BasePropertyID.SMS_CPID_VALUE_ID);  
  173.         pwdName = configService.getConfig(BasePropertyID.SMS_PWD_NAME_ID);  
  174.         pwdValue = configService.getConfig(BasePropertyID.SMS_PWD_VALUE_ID);  
  175.         pidName = configService.getConfig(BasePropertyID.SMS_PID_NAME_ID);  
  176.         pidValue = configService.getConfig(BasePropertyID.SMS_PID_VALUE_ID);  
  177.         phoneName = configService.getConfig(BasePropertyID.SMS_PHONE_NAME_ID);  
  178.         msgName = configService.getConfig(BasePropertyID.SMS_MSG_NAME_ID);  
  179.         maxLength = configService.getConfigByInteger(BasePropertyID.SMS_MSG_MAXLENGTH_ID);  
  180.           
  181.     }  
  182.       
  183.     private String getResponseMsg(String code){  
  184.         String msg = "未知返回值:" + code;  
  185.         if ("1".equals(code)) {  
  186.             msg = "手機號碼非法";  
  187.         } else if ("2".equals(code)) {  
  188.             msg = "用戶存在於黑名單列表";  
  189.         } else if ("3".equals(code)) {  
  190.             msg = "接入用戶名或密碼錯誤";  
  191.         } else if ("4".equals(code)) {  
  192.             msg = "產品代碼不存在";  
  193.         } else if ("5".equals(code)) {  
  194.             msg = "IP非法";  
  195.         } else if ("6".equals(code)) {  
  196.             msg = "源號碼錯誤";  
  197.         } else if ("7".equals(code)) {  
  198.             msg = "調用網關錯誤";  
  199.         } else if ("8".equals(code)) {  
  200.             msg = "消息長度超過60";  
  201.         } else if ("-1".equals(code)) {  
  202.             msg = "短信內容爲空";  
  203.         } else if ("-2".equals(code)) {  
  204.             msg = "手機號爲空";  
  205.         }else if ("-3".equals(code)) {  
  206.             msg = "郵件服務初始化異常";  
  207.         }else if ("-4".equals(code)) {  
  208.             msg = "短信接口異常";  
  209.         }  
  210.         return msg;  
  211.     }  
  212.   
  213.       
  214. }  

    和郵件發送是不是很類似,相信大家應該會理解吧。O(∩_∩)O哈哈~,我這裏發送的配置信息都直接初始化在了java代碼裏,大家也可以試着將其配置在xml文件裏,這樣更改更方便。

發佈了27 篇原創文章 · 獲贊 10 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章