1. spring mvc工程中引入相关freemarker\mail的包
如:pom.xml中加入类似
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.5.0-b01</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.21</version>
</dependency>

2.编写邮件发送接口TemplateEmailService.java与实现类TemplateEmailServiceImpl.java:

import java.util.Map;

public interface TemplateEmailService
{
/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName);
}

import java.io.File;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.vipshop.service.TemplateEmailService;

import freemarker.template.Template;

/**
* 发送邮件 可以自己编写freemarker模板
*
* @author sea.zeng
* @email sea.zeng@vipshop.com 2014-11-20
*/
public class TemplateEmailServiceImpl implements TemplateEmailService
{

private JavaMailSender sender;

private FreeMarkerConfigurer freeMarkerConfigurer = null;// FreeMarker的技术类

public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer)
{
this.freeMarkerConfigurer = freeMarkerConfigurer;
}

public void setSender(JavaMailSender sender)
{
this.sender = sender;
}

/**
* 生成html模板字符串
*
* @param root 存储动态数据的map
* @return
*/
private String getMailText(Map<String, Object> rootMap, String templateName)
{
String htmlText = "";
try
{
// 通过指定模板名获取FreeMarker模板实例
Template tpl = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);
htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, rootMap);
}
catch (Exception e)
{
e.printStackTrace();
}

return htmlText;
}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName)
{
try
{

MimeMessage msg = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, false, "UTF-8");
helper.setFrom(from);
helper.setTo(toEmail);
if (null != cc)
{
helper.setCc(cc);
}

helper.setSubject(subject);

Map map = new HashMap();
map.put("rootMap", rootMap);

String htmlText = getMailText(map, templateName);// 使用模板生成html邮件内容
helper.setText(htmlText, true);

// 以下仅做示范(如何增加本地文件、远程URI图片),sea.zeng 2014-11-27
// helper.addAttachment("唯品会.png", new FileSystemResource(new
// File("E:\\svn\\Testing\\Automation\\Tools\\TestPlatformApi\\Trank\\mobilet\\target\\vips-mobile\\images\\vip_logo.png")));
// helper.addAttachment("明细.jpg", new UrlResource("http://192.168.32.219:8080/mobilet/images/demo.jpg"));
// System.out.println(htmlText);
sender.send(msg);
System.out.println("成功发送模板邮件----" + templateName);
return true;
}
catch (MailException e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;
}
catch (MessagingException e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;

}

}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMailWithAttachment(Map rootMap, String from, String[] toEmail, String[] cc,
String subject, String templateName)
{
try
{

MimeMessage msg = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, "UTF-8");
helper.setFrom(from);
helper.setTo(toEmail);
if (null != cc)
{
helper.setCc(cc);
}

helper.setSubject(subject);

Map map = new HashMap();
map.put("rootMap", rootMap);

String htmlText = getMailText(map, templateName);// 使用模板生成html邮件内容
helper.setText(htmlText, true);

File fp = new File("/趋势图分析.html");
PrintWriter pfp = new PrintWriter(fp);
pfp.print(htmlText);
pfp.close();
helper.addAttachment("趋势图分析.html", new FileSystemResource(fp));

// 以下仅做示范(如何增加本地文件、远程URI图片),sea.zeng 2014-11-27
// helper.addAttachment("XXXpng", new FileSystemResource(new
// File("E:\\FILEURL\\images\\vip_logo.png")));
// helper.addAttachment("明细.jpg", new UrlResource("http://URL/images/demo.jpg"));

sender.send(msg);
System.out.println("成功发送模板邮件----" + templateName);
return true;
}
catch (Exception e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;
}

}
}

3. 新增加applicationContext-mail.xml,并包含加入到主applicationContext.xml中( <import resource="classpath:applicationContext-mail.xml" /> ):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<bean id="freeMarker" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="classpath:mailtemplates"/><!--指定模板文件目录-->
<property name="freemarkerSettings"><!-- 设置FreeMarker环境属性-->
<props>
<prop key="template_update_delay">60</prop><!--刷新模板的周期,单位为秒-->
<prop key="default_encoding">UTF-8</prop><!--模板的编码格式 -->
<prop key="locale">zh_CN</prop><!-- 本地化设置-->
</props>
</property>
</bean>

<bean id="templateEmailService" class="com.xxx.service.impl.TemplateEmailServiceImpl">
<property name="sender" ref="mailsender"></property>
<property name="freeMarkerConfigurer" ref="freeMarker"></property>
</bean>

<bean id="mailsender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host">
<value>smtp.163.com</value>
</property>
<property name="port">
<value>465</value>
</property>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.timeout">25000</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> //ssl邮箱
<prop key="mail.smtp.socketFactory.fallback">false</prop>
</props>
</property>
<property name="username">
<value>邮箱账号</value>
</property>
<property name="password">
<value>密码</value>
</property>
</bean>

</beans>

4. 配置邮件freemarker模板functionFail.ftl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>重要功能检查异常预警</title>

<style type="text/css">
body { font-family: 'trebuchet MS', 'Lucida sans', Arial; font-size: 12px;}
table { *border-collapse: collapse; border-spacing: 0; width: 100%; font-size: 12px; }
.bordered { border: solid #ccc 1px; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 1px 1px #ccc; -moz-box-shadow: 0 1px 1px #ccc; box-shadow: 0 1px 1px #ccc;}
.bordered tr:hover { background: #fbf8e9; -o-transition: all 0.1s ease-in-out; -webkit-transition: all 0.1s ease-in-out; -moz-transition: all 0.1s ease-in-out; -ms-transition: all 0.1s ease-in-out; transition: all 0.1s ease-in-out; } .bordered td, .bordered th { border-left: 1px solid #ccc; border-top: 1px solid #ccc; padding: 5px; text-align: left; }
.bordered th { background-color: #dce9f9; background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); background-image: linear-gradient(top, #ebf3fc, #dce9f9); -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset; box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; border-top: none; text-shadow: 0 1px 0 rgba(255,255,255,.5); }
.bordered td:first-child, .bordered th:first-child { border-left: none;}
.bordered th:first-child { -moz-border-radius: 6px 0 0 0; -webkit-border-radius: 6px 0 0 0; border-radius: 6px 0 0 0;}
.bordered th:last-child { -moz-border-radius: 0 6px 0 0; -webkit-border-radius: 0 6px 0 0; border-radius: 0 6px 0 0;}
.bordered th:only-child{ -moz-border-radius: 6px 6px 0 0; -webkit-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0;}
.bordered tr:last-child td:first-child { -moz-border-radius: 0 0 0 6px; -webkit-border-radius: 0 0 0 6px; border-radius: 0 0 0 6px;}
.bordered tr:last-child td:last-child { -moz-border-radius: 0 0 6px 0; -webkit-border-radius: 0 0 6px 0; border-radius: 0 0 6px 0;}
.unusual{font-weight:700; background-color:#FF0000}
</style>

</head>

<body>

<p align="center" ><h2>重要功能检查异常提醒</h2> </p>

<br /><br />

<h3><strong>详情:</strong></h3>

<table width='898' class='bordered'>

<tr>
<th width='138' >产品</th>
<th width='131' >设备</th>
<th width='108' >版本</th>
<th width='151' >功能</th>
<th width='103' >时间</th>
<th width='103' >结果</th>
<th width='142' >备注</th>
</tr>

<#if rootMap.failList?? && (rootMap.failList?size > 0) >

<#list rootMap.failList as failResult>
<tr>
<td>${failResult.product?default("")}</td>
<td>${failResult.device?default("")}</td>
<td>${failResult.version?default("")}</td>
<td>${failResult.testFeature?default("")}</td>
<td>${failResult.createTime[0..18]?default("")} </td>
<td>${failResult.result?default("")}</td>
<td>${failResult.remark?default("")}</td>
</#list>

</table>

</#if>

</body>

</html>

5. 调用如创建job,FunctionFailCheckJob.java

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xxx.dao.vo.TestReport;
import xxx.service.TestReportService;

public class FunctionFailCheckJob
{

private TestReportService testReportService;

public void setTestReportService(TestReportService testReportService)
{
this.testReportService = testReportService;
}

@SuppressWarnings({"unused", "unchecked"})
public void sendMail()
{

SimpleDateFormat df3 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
boolean result = false;
boolean resultEmpty = false;
try
{

String subject = df3.format(new Date()) + "----重要功能异常提醒";
String templateName = "functionFail.ftl";

String from = "xxx@xxx.com";
String[] toEmail =
{"sea@xxx.com"};
String[] cc = {"xx@xxx.com"};

@SuppressWarnings("rawtypes")
Map rootMap = new HashMap<>();
// 初始化模板数据----重要功能检查部分 半小时内失败记录
List<TestReport> failList = testReportService.queryFailFunctionAgo30Minute();

if (null != failList && 0 < failList.size())
{
rootMap.put("failList", failList);
result = testReportService.sendTemplateMail(rootMap, from, toEmail, cc, subject, templateName);
}
else
{
resultEmpty = true;
}

}
catch (Exception e)
{
e.printStackTrace();
}

}

}

6.testReportService实现类TestReportServiceImpl.java中实现

public class TestReportServiceImpl implements TestReportService
{

.....
private TemplateEmailService templateEmailService;

public void setTestReportDao(TestReportDao testReportDao)
{
this.testReportDao = testReportDao;
}

public void setTemplateEmailService(TemplateEmailService templateEmailService)
{
this.templateEmailService = templateEmailService;
}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return boolean
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName)
{

return templateEmailService.sendTemplateMail(rootMap, from, toEmail, cc, subject, templateName);
}
...

}

7. 整个邮件配置和调用完成,配置个spring中的定时job与业务bean这些就省略了,不是我要讲的重点

本着资源共享的原则,欢迎各位朋友在此基础上完善,并进一步分享,让我们的实现更加优雅。如果有任何疑问和需要进一步交流可以加我QQ 1922003019或者直接发送QQ邮件给我沟通

sea 20150610  中国:广州: VIP

spring mvc + freemarker优雅的实现邮件定时发送的更多相关文章

  1. Spring MVC+FreeMarker简介

    最近做项目,刚接触到SpringMVC与FreeMarker框架,就简单介绍一下自己的理解,不正确的地方请大家指教!! 1.Spring MVC工作原理: 用户发送请求--->前端服务器去找相对 ...

  2. Spring MVC freemarker使用

    什么是 FreeMarker? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具. 它不是面向最终用 ...

  3. spring mvc如何优雅的使用fastjson

    1. 在spring mvc中配置fastjson <!-- 设置配置方案 --> <mvc:annotation-driven> <!-- 设置不使用默认的消息转换器 ...

  4. spring MVC +freemarker + easyui 实现sql查询和执行小工具总结

    项目中,有时候线下不能方便的连接项目中的数据源时刻,大部分的问题定位和处理都会存在难度,有时候,一个小工具就能实时的查询和执行当前对应的数据源的库.下面,就本人在项目中实际开发使用的小工具,实时的介绍 ...

  5. java实现邮件定时发送

    最近做项目时客户提出了一个需求:系统定时发送E-mail到其客户,达到通知的效果.先将实例分享给大家,如果确实有一些帮助的话,请大家来点掌声! 首先介绍java定时器(java.util.Timer) ...

  6. SPring中quartz的配置(可以用实现邮件定时发送,任务定时执行,网站定时更新等)

    http://www.cnblogs.com/kay/archive/2007/11/02/947372.html 邮件或任务多次发送或执行的问题: 1.<property name=" ...

  7. spring mvc + freemarker 整合

    <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.s ...

  8. Spring MVC + freemarker实现半自动静态化

    这里对freemarker的代码进行了修改,效果:1,请求.do的URL时直接生成对应的.htm文件,并将请求转发到该htm文件2,自由控制某个页面是否需要静态化原理:对org.springframe ...

  9. QQ邮件定时发送天气预报

    1.首先利用request库去请求数据,天气预报使用的是和风天气的API(www.heweather.com/douments/api/s6/weather-forecast) 2.利用python的 ...

随机推荐

  1. decorators.xml的用法 (转)

    spring,hibernate框架做的,对了,还有jQuery. 我用jquery做异步请求到后台,生成json数据返回前台生成下拉输入框,请求到后台以后,成功生成了json数据并根据struts的 ...

  2. jq--回到顶部

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. c头文件包含关系--记今天调试的郁闷经历

    c头文件包含关系--记今天调试的郁闷经历 彭会锋 2016-08-05  21:54:08 c头文件的包含

  4. $('#checkbox').attr('checked'); 返回的是checked或者是undefined解决办法

    $('#checkbox').attr('checked'); 返回的是checked或者是undefined解决办法 <input type='checkbox' id='cb'/>  ...

  5. zju 1091

    // Traveling Knight Problem #include "stdafx.h" #include <string> #include <strin ...

  6. ARM的启动和中断向量表

    启动的方式 对于S3C2440而言,启动的方式有两种,一是Nor Flash方式启动,二是Nand Flash方式启动. 使用Nor Flash方式启动 Nor Flash的地址范围如下 0x0000 ...

  7. 漫谈iOS Crash收集框架

    漫谈iOS Crash收集框架   Crash日志收集 为了能够第一时间发现程序问题,应用程序需要实现自己的崩溃日志收集服务,成熟的开源项目很多,如 KSCrash,plcrashreporter,C ...

  8. Java 迭代器理解

    1.Iterator(迭代器) 作为一种设计模式,迭代器可以用于遍历一个对象,对于这个对象的底层结构不必去了解. java中的Iterator一般称为“轻量级”对象,创建它的代价是比较小的.这里笔者不 ...

  9. tsne降维可视化

    Python代码:准备训练样本的数据和标签:train_X4000.txt.train_y4000.txt 放于tsne.py当前目录.(具体t-SNE – Laurens van der Maate ...

  10. ODBC错误处理

    ODBC 中的错误处理 ODBC 中的错误是使用来自每个 ODBC 函数调用的返回值和 SQLError 函数或 SQLGetDiagRec 函数的返回值进行报告的.SQLError 函数用于 ODB ...