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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章