最近有需實現郵件發送的功能,爲了讓郵件界面和業務數據分離,故採用Velocity模板引擎。需引入velocity的時候,在Maven配置文件中添加以下依賴:css
<dependency> <groupId>velocity</groupId> <artifactId>velocity</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>velocity-tools</groupId> <artifactId>velocity-tools</artifactId> <version>2.0-beta1</version> </dependency>
接着在Spring的配置文件中定義添加以下配置:html
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> <property name="velocityProperties"> <props> <prop key="resource.loader">file</prop> <prop key="file.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop> <prop key="file.resource.loader.cache">false</prop> <prop key="file.resource.loader.modificationCheckInterval">3</prop> <prop key="input.encoding">UTF-8</prop> <prop key="output.encoding">UTF-8</prop> </props> </property> </bean> <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host"> <value>${mail.host}</value> </property> <property name="port"> <value>${mail.port}</value> </property> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">${mail.smtp.auth}</prop> <prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop> </props> </property> <property name="username"> <value>${mail.username}</value> </property> <property name="password"> <value>${mail.password}</value> </property> </bean>
須要在spring配置文件中加入以下配置:java
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:config.properties</value> </property> </bean>
並在src/main/resources目錄下的config.properties文件中加入配置:git
mail.host=mail.ylmob.com mail.port=25 mail.username=pay@ylmob.com mail.password=************* mail.smtp.auth=true mail.smtp.timeout=25000
有時習慣查看源碼,可是Maven私服上面並無源碼,只能下載velocity-1.5.zip,並在解壓,按照圖中的指示操做就能夠附加源碼:spring
。數據庫
附加源碼以後,選中你想看源碼的類,按下F3鍵,就進入源碼中。
apache
org.apache.velocity.runtime.RuntimeConstants中定義了key值信息,部門key值以下:bootstrap
/** * Key used to retrieve the names of the resource loaders to be used. In a properties file they may appear as the following: * * <p>resource.loader = classpath</p> */ String RESOURCE_LOADER = "resource.loader"; /** The public handle for setting a path in the FileResourceLoader. */ String FILE_RESOURCE_LOADER_PATH = "file.resource.loader.path"; /** The public handle for turning the caching on in the FileResourceLoader. */ String FILE_RESOURCE_LOADER_CACHE = "file.resource.loader.cache";
定義模板的輸入和輸出模板編碼的配置是:緩存
<prop key="input.encoding">UTF-8</prop> <prop key="output.encoding">UTF-8</prop>
配置檢查模板更改時間間隔:app
<prop key="file.resource.loader.modificationCheckInterval">3</prop>
配置是否啓用模板緩存:
<prop key="file.resource.loader.cache">false</prop>
配置模板路徑:
<prop key="file.resource.loader.path">${path}</prop>
配置模板加載器類型:
<prop key="resource.loader">file</prop>
配置加載器類:
<prop key="file.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
定義一個用於發送郵件接口IMailSenderService,具體代碼以下:
package com.astep.yunpay.service; import java.util.Map; /** * @Author DJM * @CreateDate:2015-05-06 13:57:20 * @UpdateDate:2015-05-06 13:57:20 * @Deprecated:Send e-mail */ public interface IMailSenderService { public void sendMailWithVelocityTemplate(String mailSubject, String templateLocation, Map<String, Object> velocityContext); }
再寫一個實現IMailSenderService接口的實現類MailSenderService,具體代碼以下:
package com.astep.yunpay.service.impl; import java.util.Map; import javax.annotation.Resource; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.velocity.app.VelocityEngine; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.springframework.ui.velocity.VelocityEngineUtils; import com.astep.yunpay.service.IMailSenderService; import com.astep.yunpay.service.ISsPropertyService; /** * @Author DJM * @CreateDate:2015-05-06 13:57:20 * @UpdateDate:2015-05-06 13:57:20 * @Deprecated:Send e-mail */ @Service("mailSenderService") public class MailSenderService implements IMailSenderService { @Autowired private ISsPropertyService ssPropertyService; @Resource private JavaMailSender javaMailSender; @Resource private VelocityEngine velocityEngine; @Override public void sendMailWithVelocityTemplate(String mailSubject, String templateLocation, Map<String, Object> velocityContext){ MimeMessage mailMessage = javaMailSender.createMimeMessage(); MimeMessageHelper messageHelper; try { messageHelper = new MimeMessageHelper(mailMessage, true, "utf-8"); // 設置郵件接收人 if(ssPropertyService.getByKey("system.mail.to")==null||ssPropertyService.getByKey("system.mail.to").equals("")){ return; } messageHelper.setTo(ssPropertyService.getByKey("system.mail.to").trim().split(";")); // 設置郵件發送人 messageHelper.setFrom(ssPropertyService.getByKey("mail.from").trim()); messageHelper.setSubject(mailSubject); String mailText = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateLocation, "utf-8", velocityContext); messageHelper.setText(mailText, true); javaMailSender.send(mailMessage); } catch (MessagingException e) { e.printStackTrace(); } } }
須要在代碼中注意代碼中,
messageHelper.setFrom(ssPropertyService.getByKey("mail.from").trim());
能夠自由配置爲shabi@shabi.com、laopozhaoxue@laopo.com、meinv@img.com等,只會影響下圖中紅色框框中的顯示部分,郵件其實是由pay@ylmob.com發送的。假如咱們配置duoshengwa@laopo.com,紅色框框中顯示將是duoshengwa,就至關於給pay@ylmob.com穿上一層皮,即便發垃圾郵件,通常也不會被別人知道。隨便說句,「mail.from」和"system.mail.to"系統後臺配置的屬性,存放於數據庫中的數據。
此次需求是天天早晨八點發送排名前十位的內容提供商的排名以及金額統計詳細和應用排名以及金額統計詳細郵件。有了MailSenderService類,只須要傳入郵件主題、模板文件的路徑和一個Map<String, Object>類型的對象model,源碼中的註釋對model給出了說明
@param model the Map that contains model names as keys and model objects as values
package com.astep.yunpay.task; /** * @Author DJM */ public interface ITopTenCpAndAppDailyCensusSendEmailTaskService { public void email(); }
實現該接口的類爲:
package com.astep.yunpay.task.impl; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import com.astep.common.util.CalculateUtil; import com.astep.common.util.DateUtil; import com.astep.common.util.DigitUtil; import com.astep.yunpay.service.IMailSenderService; import com.astep.yunpay.service.ISsPropertyService; import com.astep.yunpay.service.comprehensive.IComprehensiveService; import com.astep.yunpay.task.ITopTenCpAndAppDailyCensusSendEmailTaskService; /** * @Author DJM * @Date:2015年03月18日 * @Time:上午11:10:25 * @Description:郵件發送每日TOP10的CP和應用統計報表 */ @Service public class TopTenCpAndAppDailyCensusSendEmailTaskService implements ITopTenCpAndAppDailyCensusSendEmailTaskService { @Autowired ISsPropertyService ssPropertyService; @Autowired IComprehensiveService comprehensiveService; @Autowired private IMailSenderService mailSenderService; private static boolean isRunning = false; @Scheduled(cron = "0 0 8 * * *") //開發調試所採用的調度時間 //@Scheduled(cron = "0/30 * * * * *") //開發調試所採用的調度時間 public void email() { if (isRunning) { return; } isRunning = true; Map<String, Object> velocityCpParameter = new HashMap<String, Object>(); velocityCpParameter = enchaseParameter(velocityCpParameter, false); mailSenderService.sendMailWithVelocityTemplate("每日TOP10的CP統計報表", "velocity/VelocityTemplateOfTopTenCpDailyCensusMail.vm", velocityCpParameter); Map<String, Object> velocityAppParameter = new HashMap<String, Object>(); velocityAppParameter = enchaseParameter(velocityAppParameter, true); mailSenderService.sendMailWithVelocityTemplate("每日TOP10的APP統計報表", "velocity/VelocityTemplateOfTopTenAppDailyCensusMail.vm", velocityAppParameter); isRunning = false; } public Map<String, Object> enchaseParameter(Map<String, Object> velocityParameter, boolean isGourpApp){ velocityParameter.put("mailPlatformFlag", ssPropertyService.getByKey("mail.platform.flag") == null ? "": ssPropertyService.getByKey("mail.platform.flag")); velocityParameter.put("date", DateUtil.formatDate(DateUtil.addDays(new Date(), -1))); velocityParameter.put("comprehensiveList", getComprehensiveList(isGourpApp)); velocityParameter.put("summationMap", getSummationMap(getComprehensiveList(isGourpApp))); return velocityParameter; } public List<Map<String, Object>> getComprehensiveList(boolean isGourpApp){ Map<String, Object> condition = new HashMap<String, Object>(); Date addTimeStart = DateUtil.getDayBegin(DateUtil.addDays(new Date(), -1)); Date addTimeEnd = DateUtil.getDayEnd(addTimeStart); if(!isGourpApp){ condition.put("screening", true); } condition.put("screeningTop", true); condition.put("addTimeStart", addTimeStart); condition.put("addTimeEnd", addTimeEnd); List<Map<String, Object>> comprehensiveList = new ArrayList<Map<String, Object>>(); comprehensiveList = comprehensiveService.census(condition, "cpDailyCensus"); return comprehensiveList; } public Map<String, Object> getSummationMap(List<Map<String, Object>> comprehensiveList){ Map<String, Object> summationMap = new HashMap<String, Object>(); int coSuccessSummation=0, poSuccessSummation=0, moSuccessSummation=0, mrSuccessSummation=0; if(comprehensiveList!=null && comprehensiveList.size()>0){ for(Map<String, Object> record: comprehensiveList){ coSuccessSummation+=DigitUtil.obtainWithoutDecimal(record.get("coS")); poSuccessSummation+=DigitUtil.obtainWithoutDecimal(record.get("poS")); moSuccessSummation+=DigitUtil.obtainWithoutDecimal(record.get("moS")); mrSuccessSummation+=DigitUtil.obtainWithoutDecimal(record.get("mrS")); } } summationMap.put("coSuccessSummation", coSuccessSummation); summationMap.put("poSuccessSummation", poSuccessSummation); summationMap.put("moSuccessSummation", moSuccessSummation); summationMap.put("mrSuccessSummation", mrSuccessSummation); summationMap.put("summationPercent", CalculateUtil.quotient(mrSuccessSummation, poSuccessSummation)); return summationMap; } public String toYuan(Object object){ int number = DigitUtil.obtainWithoutDecimal(object); Integer result = number/100; return result.toString(); } }
velocity模板文件爲:
##author: DJM <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>每日TOP10的APP統計報表</title> <style> #include("velocity/css/bootstrap.css") </style> </head> <body> <h3><span class="label label-success">${mailPlatformFlag}-每日TOP10的APP統計報表(${date})</span></h3> <div class="panel panel-danger"> <div></div> <div> <table class="table table-bordered table-hover"> <tr> <td title="時間">時間</td> <td title="應用名稱">應用名稱</td> <td title="所屬CP">所屬CP</td> <td title="確認訂單金額">確認訂單金額</td> <td title="PO成功金額">PO成功金額</td> <td title="MO成功金額">MO成功金額</td> <td title="MR成功金額">MR成功金額</td> <td title="計費轉化率">計費轉化率</td> </tr> #foreach($comprehensive in ${comprehensiveList}) <tr> <td>${comprehensive.censusDay}</td> <td title="${comprehensive.appId}">${comprehensive.appName}</td> <td>${comprehensive.shortName}</td> #set($coS=${comprehensive.coS}/100) <td>${coS}元</td> #set($poS=${comprehensive.poS}/100) <td>${poS}元</td> #set($moS=${comprehensive.moS}/100) <td>${moS}元</td> #set($mrS=${comprehensive.mrS}/100) <td>${mrS}元</td> #if(${comprehensive.mrS} <= 0 || ${comprehensive.poS} <= 0) <td>0%</td> #else #set($comprehensivePercent=${comprehensive.mrS}*10000/${comprehensive.poS}/100) <td>${comprehensivePercent}%</td> #end </tr> #end <tr> <td>合計</td> <td>-</td> <td>-</td> #set($coSuccessSummation=${summationMap.coSuccessSummation}/100) <td>${coSuccessSummation}元</td> #set($poSuccessSummation=${summationMap.poSuccessSummation}/100) <td>${poSuccessSummation}元</td> #set($moSuccessSummation=${summationMap.moSuccessSummation}/100) <td>${moSuccessSummation}元</td> #set($mrSuccessSummation=${summationMap.mrSuccessSummation}/100) <td>${mrSuccessSummation}元</td> <td>${summationMap.summationPercent}%</td> </tr> </table> </div> </div> <h3> <span class="glyphicon glyphicon-link" aria-hidden="true"></span> <span class="label label-info"><a href="http://p.918ja.com:9020/login.do">進入移動支付統一合做平臺</a></span> </h3> </body> </html>
使用#include命令引入bootstrap.css文件:
<style> #include("velocity/css/bootstrap.css") </style>
發送的郵件內容爲: