java郵件傳送和簡訊傳送(一)
那先來說說郵件傳送。按照按介面程式設計的習慣,當然先要定義一個郵件傳送的介面,再實現其介面,完成郵件傳送Service層的程式碼。這個順序我想大家沒什麼反對意見吧。
首先咱們先定義一個訊息傳送介面,它是郵件傳送與簡訊傳送的上層介面。
[java] view plaincopyprint?- /**
- * 功能: 系統訊息傳送服務 <p>
- * 用法:
- * @version 1.0
- */
- publicinterface MessageService {
- /**
- * 根據訊息模板表中的訊息編號取得訊息模板,填充,傳送
- *
- * @param bmtCode 訊息模板表中的訊息編號
- * @param params 填充模板內容的引數
- * @param to 訊息的接收人
- * @throws CheckException 模板不存在,或是傳送訊息出現異常
- */
- publicvoid sendMessage(String bmtCode,Map params, String... to) throws CheckException;
- }
再來定義一下郵件傳送器介面,由於我這裡是通過velocity模板傳送郵件的,所以如下定義了介面:
[java] view plaincopyprint?- /**
- * 郵件傳送器
- * @usage
- */
- publicinterface TempletEmailSender {
- /**
- * @param from 發件人郵箱
- * @param to 收件人郵箱
- * @param subject 郵件主題
- * @param templet 模板
- * @param paramMap 模板引數資訊
- * @throws CheckException
- */
- publicvoid sendEmailByTemplet(String from, String to, String subject,String templet, Map<String, Object> paramMap) throws CheckException;
- /**
- * @param from 發件人郵箱
- * @param to 收件人郵箱(多個)
- * @param subject 郵件主題
- * @param templet 模板
- * @param paramMap 模板引數資訊
- * @throws CheckException
- */
- publicvoid sendEmailByTemplet(String from, String[] to, String subject,String templet, Map<String, Object> paramMap) throws CheckException;
- /**
- * @param mail 郵件物件
- * @param templet 模板
- * @param paramMap 模板引數資訊
- * @throws CheckException
- */
- publicvoid sendEmailByTemplet(Mail mail,String templet, Map<String, Object> paramMap) throws CheckException;
- }
接著實現郵件傳送的介面:
[java] view plaincopyprint?- /**
- * 郵件傳送器預設實現
- */
- publicclass TempletEmailSenderImpl implements TempletEmailSender{
- @Autowired
- @Qualifier("emailSenderImpl_commons")
- private EmailSender emailSender;
- @Override
- publicvoid sendEmailByTemplet(String from, String to,String subject, String templet, Map<String, Object> paramMap) throws CheckException {
- sendEmailByTemplet(from, new String[]{to}, subject, templet, paramMap);
- }
- @Override
- publicvoid sendEmailByTemplet(String from, String[] to, String subject, String templet, Map<String, Object> paramMap) throws CheckException {
- // 解析模板
- String content ;
- try {
- content = VelocityParserUtil.getInstance().parseVelocityTemplate(templet, paramMap);
- } catch (Throwable t) {
- thrownew CheckException(t);
- }
- emailSender.sendEmail(from, to, subject, content);
- }
大家看到了上面的實現裡注入了EmailSender,它也是一個介面,它的實現裡注入了JavaMail提供的郵件傳送介面。定義了兩層是為了區分有模板的傳送和無模板的傳送。我們來看看它是什麼樣的:
[java] view plaincopyprint?- /**
- * 郵件傳送器
- * @usage
- */
- publicinterface EmailSender {
- /**
- * 傳送郵件
- * @param from 發件人
- * @param to 收件人
- * @param subject 郵件主題
- * @param mailBody 郵件內容
- * @throws CheckException 引數校驗失敗或傳送郵件失敗時,丟擲此異常
- */
- void sendEmail(String from, String to, String subject, String mailBody) throws CheckException;
- /**
- * 傳送郵件
- * @param from 發件人
- * @param to 多個收件人
- * @param subject 郵件主題
- * @param mailBody 郵件內容
- * @throws CheckException 引數校驗失敗或傳送郵件失敗時,丟擲此異常
- */
- void sendEmail(String from, String[] to, String subject, String mailBody) throws CheckException;
- /**
- * 傳送郵件
- * @param mail 郵件
- * @throws CheckException 引數校驗失敗或傳送郵件失敗時,丟擲此異常
- */
- void sendEmail(Mail mail) throws CheckException;
- }
接著實現這個EmailSender介面:
[java] view plaincopyprint?- **
- * JAVA MAIL實現
- */
- publicclass EmailSenderImpl implements EmailSender,InitializingBean{
- /**
- * Logger for this class
- */
- privatestaticfinal Logger logger = Logger.getLogger(EmailSenderImpl.class);
- @Autowired
- private ConfigService configService;
- private JavaMailSenderImpl sender; // 實際的傳送實現
- @Override
- publicvoid sendEmail(String from, String to, String subject, String mailBody) throws CheckException {
- sendEmail(from, new String[]{to}, subject, mailBody);
- }
- @Override
- publicvoid sendEmail(String from, String[] to, String subject, String mailBody) throws CheckException {
- // 構造MAIL物件
- Mail mail = new Mail();
- mail.setFrom(from);
- mail.setTo(to);
- mail.setSubject(subject);
- mail.setContent(mailBody);
- sendEmail(mail);
- }
- @Override
- publicvoid sendEmail(Mail mail) throws CheckException {
- // 檢查必要引數
- if (mail == null ){
- thrownew CheckException("mail can not be null.");
- }
- if (ArrayUtils.isEmpty(mail.getTo())){
- thrownew CheckException("收件人不能為空");
- }
- MimeMessageHelper helper = null;
- try {
- helper = new MimeMessageHelper(sender.createMimeMessage(), true, "UTF-8");
- // 發件人
- if (mail.getFrom() != null) {
- if (mail.getFromName() == null) {
- helper.setFrom(mail.getFrom());
- } else {
- helper.setFrom(mail.getFrom(), mail.getFromName());
- }
- }
- // 收件人
- helper.setTo(mail.getTo());
- // 抄送人
- if (mail.getCc() != null) {
- helper.setCc(mail.getCc());
- }
- // 密送人
- if (mail.getBcc() != null) {
- helper.setBcc(mail.getBcc());
- }
- // 郵件主題
- helper.setSubject(mail.getSubject());
- // 郵件內容
- helper.setText(mail.getContent(), mail.isHtmlFormat());
- // 附件
- if (mail.getAttachments() != null) {
- for ( MailAttachment attachment : mail.getAttachments()) {
- helper.addAttachment(attachment.getFileName(),attachment.getFile());
- }
- }
- // 傳送時間
- helper.setSentDate(new Date());
- } catch (UnsupportedEncodingException e) {
- logger.error("sendEmail(Mail)", e);
- thrownew CheckException(e) ;
- } catch (MessagingException e) {
- logger.error("sendEmail(Mail)", e);
- thrownew CheckException(e) ;
- }
- // 傳送
- try {
- sender.send(helper.getMimeMessage());
- } catch (MailException e) {
- logger.error("sendEmail(Mail)", e);
- thrownew CheckException(e) ;
- }
- }
- @Override
- publicvoid afterPropertiesSet() throws Exception {
- sender = new JavaMailSenderImpl();
- // configService讀出引數
- Properties pros = new Properties();
- pros.setProperty("mail.smtp.user", configService.getConfig(BasePropertyID.MAIL_SMTP_USER_ID));
- pros.setProperty("mail.smtp.host", configService.getConfig(BasePropertyID.MAIL_SMTP_HOST_ID));
- pros.setProperty("mail.smtp.port", configService.getConfig(BasePropertyID.MAIL_SMTP_PORT_ID));
- pros.setProperty("mail.smtp.connectiontimeout", configService.getConfig(BasePropertyID.MAIL_SMTP_CONNECTIONTIMEOUT_ID));
- pros.setProperty("mail.smtp.timeout", configService.getConfig(BasePropertyID.MAIL_SMTP_TIMEOUT_ID));
- pros.setProperty("mail.smtp.from", configService.getConfig(BasePropertyID.MAIL_SMTP_FROM_ID));
- pros.setProperty("mail.smtp.auth", configService.getConfig(BasePropertyID.MAIL_SMTP_AUTH_ID));
- sender.setJavaMailProperties(pros);
- sender.setPassword(configService.getConfig(BasePropertyID.MAIL_SMTP_PASSWORD_ID));
- }
- public ConfigService getConfigService() {
- return configService;
- }
- publicvoid setConfigService(ConfigService configService) {
- this.configService = configService;
- }
O(∩_∩)O~大家又注意到了 這個介面實現裡又注入了一個介面ConfigService 它是去讀取郵件傳送的相關配置資訊,如上所示:
// configService讀出引數
Properties pros = new Properties();
pros.setProperty("mail.smtp.user", configService.getConfig(BasePropertyID.MAIL_SMTP_USER_ID));
pros.setProperty("mail.smtp.host", configService.getConfig(BasePropertyID.MAIL_SMTP_HOST_ID));
pros.setProperty("mail.smtp.port", configService.getConfig(BasePropertyID.MAIL_SMTP_PORT_ID));
pros.setProperty("mail.smtp.connectiontimeout", configService.getConfig(BasePropertyID.MAIL_SMTP_CONNECTIONTIMEOUT_ID));
pros.setProperty("mail.smtp.timeout", configService.getConfig(BasePropertyID.MAIL_SMTP_TIMEOUT_ID));
pros.setProperty("mail.smtp.from", configService.getConfig(BasePropertyID.MAIL_SMTP_FROM_ID));
pros.setProperty("mail.smtp.auth", configService.getConfig(BasePropertyID.MAIL_SMTP_AUTH_ID));
sender.setJavaMailProperties(pros);
sender.setPassword(configService.getConfig(BasePropertyID.MAIL_SMTP_PASSWORD_ID));
而且由於涉及到引數的資料成員較多,就將他們一起封裝到了Mail類:
[java] view plaincopyprint?- /**
- * 功能: 封裝郵件物件 <p>
- * 用法:
- * @version 1.0
- */
- publicclass Mail {
- /**
- * 發件人
- */
- private String from;
- /**
- * 發件人(顯示)
- */
- private String fromName;
- /**
- * 收件人
- */
- private String[] to;
- /**
- * 抄送
- */
- private String[] cc;
- /**
- * 祕密抄送
- */
- private String[] bcc;
- /**
- * 郵件主題
- */
- private String subject;
- /**
- * 郵件內容
- */
- private String content;
- /**
- * 附件
- */
- private MailAttachment[] attachments;
- /**
- * 是否以HTML格式傳送
- */
- boolean isHtmlFormat = true;
- //getter與setter方法省略
- }
好了 整個介面都實現了,其實排除了你傳送郵件提供給郵件傳送介面的幾個引數,剩下的也就是呼叫java提供的郵件傳送的API和一些郵件傳送必備的配置資訊,必不是很難懂吧。大家肯定注意到了郵件傳送介面的velocity模板解析方法:
content = VelocityParserUtil.getInstance().parseVelocityTemplate(templet, paramMap);
它具體的實現如下所示:
[java] view plaincopyprint?- /**
- * 功能:解析velocity模板
- * <p>
- * 用法:
- *
- * @version 1.0
- */
- publicclass VelocityParserUtil {
- /**
- * Logger for this class
- */
- privatestaticfinal Logger logger = Logger.getLogger(VelocityParserUtil.class);
- privatestatic VelocityParserUtil instance = new VelocityParserUtil();
- private VelocityEngine engine = null;
- private VelocityParserUtil() {
- // init engine
- engine = new VelocityEngine();
- try {
- engine.init();
- } catch (Exception e) {
- logger.warn("VelocityParserUtil() - exception ignored", e); //$NON-NLS-1$
- }
- }
- /**
- * 返回VelocityParserUtil例項
- * @return
- */
- publicstatic VelocityParserUtil getInstance() {
- return instance;
- }
- /**
- * 解析velocity模板
- * @param vtl
- * @param model
- * @return String
- * @throws ParseErrorException
- * @throws MethodInvocationException
- * @throws ResourceNotFoundException
- * @throws IOException
- */
- public String parseVelocityTemplate(String vtl, Map model)
- throws ParseErrorException, MethodInvocationException,
- ResourceNotFoundException, IOException {
- if (logger.isDebugEnabled()) {
- logger.debug("parseVelocityTemplate(String, Map) - start"); //$NON-NLS-1$
- }
- VelocityContext velocityContext = new VelocityContext(model);
- StringWriter result = new StringWriter();
- engine.evaluate(velocityContext, result, null, vtl);
- String returnString = result.toString();
- if (logger.isDebugEnabled()) {
- logger.debug("parseVelocityTemplate(String, Map) - end"); //$NON-NLS-1$
- }
- return returnString;
- }
- }
我們會在其他的Service中去呼叫郵件傳送的介面,只需要在業務層裡構造好郵件傳送的介面所需引數,我們的郵件就可以傳送出去了。還有一點請大家注意,我這裡主要強調的是運用velocity模板傳送郵件,介面所需要的引數templat大家不要誤解為velocity模板的檔名,它其實velocity檔案的檔案流,是一個已經被讀入的字串。大家可以參考一下測試用例,大致可以明白是怎麼回事了。
[java] view plaincopyprint?- publicclass TempletEmailSenderTest extends BaseTestBaseForJUnit4{
- @Autowired
- @Qualifier("templetEmailSenderImpl_commons")
- private TempletEmailSender sender;
- // @Test
- publicvoid sendEmailByTemplet() throws CheckException{
- String templet = "$!{user}提醒您付款$!{amount}元";
- Map paramMap = new HashMap();
- paramMap.put("user", "吳欣");
- paramMap.put("amount", "99.9");
- sender.sendEmailByTemplet("[email protected]", "[email protected]", "模板郵件", templet, paramMap);
- }
整個郵件的傳送大家是否明瞭了呢,呵呵!
後面我們會將這個介面向上抽象,為了實現我們簡訊傳送的實現,下一篇敬請期待哦