• spring mvc + freemarker优雅的实现邮件定时发送


    1. spring mvc工程中引入相关freemarkermail的包
    如: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; 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

    本着资源共享的原则,欢迎各位朋友在此基础上完善,并进一步分享,让我们的实现更加优雅。如果有任何疑问和需要进一步交流可以留言沟通 Testner创始人(testner.club) Sea
  • 相关阅读:
    《深入理解 Java 虚拟机》学习笔记 -- 内存区域
    Guava -- 集合类 和 Guava Cache
    Spring 事务
    isEmpty 和 isBlank 区别
    @RequestBody, @ResponseBody 注解理解
    JSONObject 的使用
    loadrunner结果分析实战之页面细分
    loadrunner结果分析实战之分析图合并和分析图关联
    Linux如何查看端口被哪个进程占用?
    Loadrunner脚本录制HTTPs协议请求
  • 原文地址:https://www.cnblogs.com/sea520/p/4565323.html
Copyright © 2020-2023  润新知