这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
springboot实现发送邮件demo
1:pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.quartz</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- freemarker模版 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!-- email -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier><!--指定jdk版本-->
</dependency>
<!--quartz定时调度依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
pom.xml
2:配置文件
server.servlet.context-path=/
server.port=8080
spring.mail.host=smtp.qq.com
spring.mail.username=xxx@qq.com
#授权码需要填写自己的
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.smtp.starttls.enable=true
spring.mail.properties.smtp.starttls.required = true
spring.mail.default-encoding=UTF-8
#使用freemarker模板发送
#放置模板的位置
spring.freemarker.template-loader-path=classpath:/static/template/
spring.freemarker.suffix=.flt
spring.freemarker.enabled=true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.allow-request-override=false
spring.freemarker.check-template-location=true
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes= false
spring.freemarker.expose-spring-macro-helpers=false
3:Email实体类
import java.util.Arrays;
import java.util.HashMap;
public class Email implements Serializable {
private static final long serialVersionUID = 1L;
private String[] email; //接受方邮箱
private String subject; //主题
private String content; //内容
private String template; //模板
public Email() {
super();
}
public Email(String[] email, String subject, String content, String template) {
this.email = email;
this.subject = subject;
this.content = content;
this.template = template;
}
public String[] getEmail() {
return email;
}
public void setEmail(String[] email) {
this.email = email;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
}
4:IEmailService接口
import javax.mail.MessagingException;
public interface IEmailService {
public void send(Email email) throws MessagingException;//发送邮件
public void pollQueue(Email email) throws InterruptedException;//把邮件放入队列中
}
5:利用BlockingQueue保存Email
import com.example.quartz.common.entity.Email;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* 保存邮件的队列
* 设计为单例模式
*/
public class Mailqueue {
public static final int QUEUE_SIZE = 100;
public static BlockingQueue<Email> queue = new LinkedBlockingQueue<>(QUEUE_SIZE);
public volatile static Mailqueue mailqueue ;
/*
*使用DCL模式
*/
public static Mailqueue getSingleton()
{
if(mailqueue == null)
{
synchronized (Mailqueue.class)
{
if(mailqueue == null)
{
mailqueue = new Mailqueue();
}
}
}
return mailqueue;
}
//入队
public void add(Email email) throws InterruptedException {
queue.put(email);
}
//出队
public Email poll() throws InterruptedException {
return queue.take();
}
//队列大小
public int size()
{
return queue.size();
}
private Mailqueue(){}
}
6:利用线程池的线程不断去读取队列是否存在Email,然后线程发送邮件
import com.example.quartz.service.IEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 消费队列
*
*/
@Component
public class ConsumeQueue {
@Autowired
IEmailService emailService;
@PostConstruct
public void start()
{
ExecutorService pool = Executors.newFixedThreadPool(2);//固定两个线程的线程池
pool.submit(new task()); //提交任务
}
class task implements Runnable{
@Override
public void run() {
System.out.println("等待接受任务");
while(true)
{
Email email = null;
try {
email = Mailqueue.getSingleton().poll();
System.out.println("接受到邮件");
if(email != null)
{
emailService.send(email);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}
}
7:EmailServiceImpl
import com.example.quartz.common.queue.Mailqueue;
import com.example.quartz.service.IEmailService;
import freemarker.core.ParseException;
import freemarker.template.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
@Service
public class EmailServiceImpl implements IEmailService {
@Autowired
JavaMailSender mailSender;//用于发送邮件
@Autowired
Configuration configuration;//freemarker
@Value("${spring.mail.username}")
public String USER_NAME;//发送者
@Value("${server.path}")
public String PATH; //模板中的图片等静态资源路径
/**
* 把邮件放进队列中
* @param email
*/
@Override
public void send(Email email) {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = null;
try {
helper = new MimeMessageHelper(message, true);
helper.setFrom(USER_NAME,"通过模板发送邮件");
helper.setTo(email.getEmail());//发送给谁
helper.setSubject(email.getSubject());//主题
Map<String, Object> model = new HashMap<>();
model.put("mail",email);
model.put("path",PATH);
Template template = configuration.getTemplate(email.getTemplate());//获得模板
String msg = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
helper.setText(msg,true);
mailSender.send(message);//正式发送邮件
} catch (MessagingException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MalformedTemplateNameException e) {
e.printStackTrace();
} catch (TemplateNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
}
@Override
public void pollQueue(Email email) throws InterruptedException {
Mailqueue.getSingleton().add(email);
}
}
利用quartz实现定时发送邮件功能
1:quartz实体
public class QuartzEntity {
private String jobName;//任务名称
private String jobGroup;//任务分组
private String description;//任务描述
private String jobClassName;//执行类
private String jobMethodName;//执行方法
private String cronExpression;//执行时间
private String triggerName;//执行时间
private String triggerState;//任务状态
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getJobClassName() {
return jobClassName;
}
public void setJobClassName(String jobClassName) {
this.jobClassName = jobClassName;
}
public String getJobMethodName() {
return jobMethodName;
}
public void setJobMethodName(String jobMethodName) {
this.jobMethodName = jobMethodName;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getTriggerName() {
return triggerName;
}
public void setTriggerName(String triggerName) {
this.triggerName = triggerName;
}
public String getTriggerState() {
return triggerState;
}
public void setTriggerState(String triggerState) {
this.triggerState = triggerState;
}
}
2:MyJob构建
import com.example.quartz.common.queue.Mailqueue;
import org.quartz.*;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@DisallowConcurrentExecution
public class MyJob implements Job , Serializable {
private static final long serialVersionUID = 1L;
@Override
public void execute(JobExecutionContext context){
JobDetail jobDetail = context.getJobDetail();
JobDataMap dataMap = jobDetail.getJobDataMap();
/**
* 获取任务中保存的方法名字,动态调用方法
*/
String methodName = dataMap.getString("jobMethodName");
try {
MyJob job = new MyJob();
Method method = job.getClass().getMethod(methodName);
method.invoke(job);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void test1() throws InterruptedException {
System.out.println("执行任务");
//往邮件队列中放入邮件
Email email = new Email();
email.setEmail(new String[]{"xxx@qq.com"});
email.setContent("测试发送邮件");
email.setSubject("定时发送邮件demo");
email.setTemplate("hh.flt");
Mailqueue.getSingleton().add(email);
}
}
3:TaskRunner
import com.example.quartz.common.entity.QuartzEntity;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 初始化任务
*/
@Component
public class TaskRunner implements ApplicationRunner {
private final static Logger LOGGER = LoggerFactory.getLogger(TaskRunner.class);
@Autowired
private Scheduler scheduler;
@Override
public void run(ApplicationArguments args) throws Exception {
//初始化任务测试发送邮件
QuartzEntity quartz = new QuartzEntity();
quartz.setJobName("测试一下");
quartz.setJobGroup("test");
quartz.setDescription("测试定时任务发送邮件");
quartz.setJobClassName("com.example.quartz.job.MyJob");
quartz.setCronExpression("*/5 * * * * ?"); //每隔5秒发送邮件
quartz.setJobMethodName("test1"); //具体的需要执行的定时任务逻辑方法名
Class cls = Class.forName(quartz.getJobClassName());
cls.newInstance();
//构建job
JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(), quartz.getJobGroup())
.withDescription(quartz.getDescription()).build();
job.getJobDataMap().put("jobMethodName","test1");
//触发的时间点
CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(quartz.getJobName(), quartz.getJobGroup())
.startNow().withSchedule(cronSchedule).build();
scheduler.scheduleJob(job,trigger); //将job和trigger交给scheduler
}
}