springboot mail+Thymeleaf模板
compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
compile 'io.ratpack:ratpack-thymeleaf:1.4.2'
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import ratpack.thymeleaf.internal.ThymeleafHttpServletRequestAdapter;
import ratpack.thymeleaf.internal.ThymeleafHttpServletResponseAdapter;
import ratpack.thymeleaf.internal.ThymeleafServletContextAdapter; import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask; /**
* Created by hujunzheng on 17/9/8.
*/
@Service
public class MailService { @Autowired
private MailProperties mailProperties; @Autowired
private JavaMailSender javaMailSender; @Autowired
private TemplateEngine templateEngine; private static final Log log = LogFactory.getLog(MailService.class);
/**
* 发送邮件
* @param userEmail
* @param templateId
*/
public void sendMail(String userEmail, Map<String, Object> params, int templateId) {
sendMailMultiParams(new String[] {userEmail}, params, templateId);
} public void sendMail(String userEmail, Object obj, int templateId) {
Map<String, Object> params = objectToMap(obj);
sendMailMultiParams(new String[] {userEmail}, params, templateId);
} public void sendMail(String userEmail, String message, String subject) {
sendSampleMail(new String[] {userEmail}, message, subject);
} public void sendMail(String[] userEmails, Map<String, Object> params, int templateId) {
sendMailMultiParams(userEmails, params, templateId);
} public void sendMail(String[] userEmails, Object obj, int templateId) {
Map<String, Object> params = objectToMap(obj);
sendMailMultiParams(userEmails, params, templateId);
} public void sendMail(String[] userEmails, String message, String subject) {
sendSampleMail(userEmails, message, subject);
} private Map<String, Object> objectToMap(Object obj) {
PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(obj.getClass());
Map<String, Object> params = new HashMap<>();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
if (key.compareToIgnoreCase("class") == 0) {
continue;
}
Optional<Method> getter = Optional.ofNullable(property.getReadMethod());
try {
Object value = getter.isPresent() ? getter.get().invoke(obj) : null;
params.put(key, value);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
return params;
} /**
* 异步 分别发送 发送邮件
* */
public List<String> asynSendMails(List<ApiPortalOperator> apiPortalOperators, Object bodyParams) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<FutureTask<String>> futureTasks = new ArrayList<>();
for (ApiPortalOperator apiPortalOperator : apiPortalOperators) {
FutureTask<String> futureTask = new FutureTask(() -> {
try {
this.sendMail(apiPortalOperator.getEmail(), bodyParams, 1);
} catch (Exception e) {
return "邮件to " + apiPortalOperator.getEmail() + " 发送异常:" + e.getMessage();
}
return "邮件to " + apiPortalOperator.getEmail() + " 发送成功";
});
futureTasks.add(futureTask);
executorService.submit(futureTask);
} List<String> result = new ArrayList<>();
for (int i=0; i<futureTasks.size(); ++i) {
FutureTask futureTask = futureTasks.get(i);
try {
result.add((String) futureTask.get());
} catch (Exception e) {
result.add("to " + apiPortalOperators.get(i).getEmail() + " 发送失败:" + e.getMessage());
}
} return result;
} /**
* 异步 多个收件人一起 发送邮件
* */
public String asynSendMail(List<ApiPortalOperator> apiPortalOperators, Object bodyParams) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
String[] userEmails = apiPortalOperators.stream().map(ApiPortalOperator::getEmail).toArray(String[]::new);
FutureTask<String> futureTask = new FutureTask(() -> {
try { this.sendMail(userEmails, bodyParams, 1);
} catch (Exception e) {
return "邮件to " + StringUtils.join(userEmails, ',') + " 发送异常:" + e.getMessage();
}
return "邮件to " + StringUtils.join(userEmails, ',') + " 发送成功";
});
executorService.submit(futureTask);
try {
return futureTask.get();
} catch (Exception e) {
e.printStackTrace();
return "邮件to " + StringUtils.join(userEmails, ',') + " 发送异常:" + e.getMessage();
}
} private void sendSampleMail(String[] userEmail, String msg, String subject) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "utf-8");
message.setTo(userEmail);
message.setFrom(new InternetAddress(mailProperties.getFrom()));
message.setSubject(subject);
message.setText(msg);
}
};
try {
this.javaMailSender.send(preparator);
} catch (Exception ex) {
log.error("Mailing Exception! user email is: {}", userEmail, ex);
}
log.info("Mail sent successfully, user email is: {}", userEmail);
} private String buildTemplateMessage(String templateName, Map<String, Object> messages) {
HttpServletRequest request = new ThymeleafHttpServletRequestAdapter();
HttpServletResponse response = new ThymeleafHttpServletResponseAdapter();
ServletContext servletContext = new ThymeleafServletContextAdapter();
WebContext context = new WebContext(request, response, servletContext);
context.setVariables(messages);
return templateEngine.process(templateName, context);
} /**
* 当发邮件时有多个不定参数时
* @param userEmail 用户邮箱
* @param params 发邮件的参数
* @param templateId
*/
private void sendMailMultiParams(String[] userEmail, Map<String, Object> params, Integer templateId) { String templateName = MailTemplate.getTemplateName(templateId); MimeMessagePreparator preparator = new MimeMessagePreparator() {
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "utf-8");
message.setTo(userEmail);
message.setFrom(new InternetAddress(mailProperties.getFrom()));
message.setSubject(MailTemplate.getTemplateSubject(templateId)); String content = buildTemplateMessage(templateName, params);
System.out.println(content);
message.setText(content, true);
}
};
try {
this.javaMailSender.send(preparator);
} catch (Exception ex) {
log.error("Mailing Exception! user email is: {}, template params are: {}, template_id is: {}", userEmail, params.toString(), templateId, ex);
}
log.info("Mail sent successfully, user email is: {}, template params: {}, template_id is: {}", userEmail, params.toString(), templateId);
}
}
Thymeleaf 中有 plain context (不支持对url参数的解析)和 web context(支持对url参数的解析)
We'll have to change our code to create a web context, instead of a plain context. Change will be here: 参考:https://github.com/ratpack/ratpack/blob/master/ratpack-thymeleaf/src/main/java/ratpack/thymeleaf/Template.java#L69-69 The IWebContext interface seems coupled to the servlet API, but after quick look at the code I don't think this will be a problem. I think we can just provide null values for things like request/session etc. that we can't provide. If that turns out to be a problem… we can look at providing implementations of those Servlet API type in so far makes sense.
最后附上一份简单的邮件模板文件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>邮件提醒</title>
</head>
<body style="margin: 0; padding: 0;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="padding: 20px; font-size: 14px;">
<tbody>
<tr>
<td><p style="margin: 0; margin-bottom: 20px;">Hi,</p></td>
</tr>
<tr>
<td><p style="margin: 0; margin-bottom: 20px;">项目<span th:text="${project}"/>的API已设计完成,请到<a href="#" th:href="@{ ${apiUrl} }">API Portal</a>上review。</p></td>
</tr>
<tr th:each="link,status : ${links}">
<td><p style="margin: 0;"><span th:text="${status.count}"/>. <span th:text="${link.method}"/> <span th:text="${link.path}"/> <span th:text="${link.description}"/> <a href="#" th:href="@{ ${link.url} }">点击查看</a></p></td>
</tr>
<tr>
<td><p style="margin: 0; margin-top: 20px;">Thanks</p></td>
</tr>
<tr>
<td><p style="margin: 0;"><span th:text="${user}"/></p></td>
</tr>
</tbody>
</table>
</body>
</html>
springboot mail+Thymeleaf模板的更多相关文章
- SpringBoot 之Thymeleaf模板.
一.前言 Thymeleaf 的出现是为了取代 JSP,虽然 JSP 存在了很长时间,并在 Java Web 开发中无处不在,但是它也存在一些缺陷: 1.JSP 最明显的问题在于它看起来像HTML或X ...
- springboot整合Thymeleaf模板引擎
引入依赖 需要引入Spring Boot的Thymeleaf启动器依赖. <dependency> <groupId>org.springframework.boot</ ...
- Springboot整合thymeleaf模板
Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用. Thymeleaf的主要目标在于提供一种可被浏览器正确显示的.格式良好的模板创建方式,因此也可以用作静态建 ...
- (二)springboot整合thymeleaf模板
在我们平时的开发中,用了很久的jsp作view显示层,但是标签库和JSP缺乏良好格式的一个副作用就是它很少能够与其产生的HTML类似.所以,在Web浏览器或HTML编辑器中查看未经渲染的JSP模板是非 ...
- 【Springboot】Springboot整合Thymeleaf模板引擎
Thymeleaf Thymeleaf是跟Velocity.FreeMarker类似的模板引擎,它可以完全替代JSP,相较与其他的模板引擎,它主要有以下几个特点: 1. Thymeleaf在有网络和无 ...
- SpringBoot系列——Thymeleaf模板
前言 thymeleaf是springboot官方推荐使用的java模板引擎,在springboot的参考指南里的第28.1.10 Template Engines中介绍并推荐使用thymeleaf, ...
- SpringBoot使用thymeleaf模板引擎
(1).添加pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...
- springboot 引入 thymeleaf 模板
第一步pom中: <!-- 引入 thymeleaf 模板依赖 --> <dependency> <groupId>org.springframework.boot ...
- SpringBoot日记——Thymeleaf模板引擎篇
开发通常我们都会使用模板引擎,比如:JSP.Velocity.Freemarker.Thymeleaf等等很多,那么模板引擎是干嘛用的? 模板引擎,顾名思义,是一款模板,模板中可以动态的写入一些参数, ...
随机推荐
- 【CTF MISC】隐写术wireshark找出图片-“强网杯”网络安全挑战赛writeup
这场CTF中有一道题是分析pcap包的.. 13.大黑阔: 从给的pcap包里把图片提取出来,是一张中国地图. 题目提示是黑阔在聊天,从数据里可以找出几段话. 思路:主要考察wireshark的过滤规 ...
- 【转】Python中的eval()、exec()及其相关函数
[转]Python中的eval().exec()及其相关函数 刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函 ...
- UML和模式应用5:细化阶段(8)---逻辑架构和UML包图
1.前言 本章是从面向分析的工作过度到软件设计 典型的OO系统设计的基础是若干架构层,如UI层.应用逻辑(领域)层 本章简要考察逻辑分层架构和相关UML表示法 2.逻辑架构和层 逻辑架构 逻辑架构是软 ...
- VMware如何给虚拟机添加新硬盘
在使用虚拟机时,若硬盘空间不足.或需要用到双硬盘或多硬盘环境时,我们可以给虚拟机新增虚拟硬盘
- oracle flashback 后主键及索引更改问题
oracle flashback 后 主键会变为bin开头,如果删除可以采用将sql复制出单独窗口,然后加上“”执行
- 003_饿了么chaosmonkey实现
背景 公司目前的服务设计大部分满足 design for failure 理念.随着业务复杂度的提升,我们很难再保证对系统故障的容错性.我们需要工具来验证服务的容错性,基于这个需求我们使用了 tc 工 ...
- ios 获取视频截图
#pragma mark -- 获取视频截图- (UIImage *)getThumbnailImage:(NSString *)videoURL{ AVURLAsset *asset = [ ...
- Oracle 网络配置与管理
[学习目标] Oracle 监听器是一个服务器端程序,用于监听所有来自客户端的请求,并为其提供数 据库服务.因此对监听器的管理与维护相当重要. 本章主要内容是描述对Oracle 监听器 ...
- python接口自动化测试七:获取登录的Cookies,并关联到下一个请求
获取登录的cookies:loginCookies = r.cookies 把获取到的cookies传入请求:cookies=loginCookies 此方法需每一次都调用登录方法,并且每一次发送请求 ...
- win7 64 下 VS2008 调试、退出时错误的解决
最近调试老程序的时候发现原来的VS2008会偶尔在调试C++程序的时候出现程序未响应的情况,开始还以为是个案,后来出现的频率越来越高完全影响心情啊!! 准备花时间解决一下这个问题.网上搜索没有发现任何 ...