untimeException(e);
}
log.info("async-job-01-end...");
}
@Async("asyncPool")
public void asyncJobPool (){
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("async-job-02-end...");
}
}
1.2 线程池
定义一个ThreadPoolTaskExecutor
线程池对象;
@Configuration
public class PoolConfig {
@Bean("asyncPool")
public Executor asyncPool () {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 线程池命名前缀
executor.setThreadNamePrefix("async-pool-");
// 核心线程数5
executor.setCorePoolSize(5);
// 最大线程数10
executor.setMaxPoolSize(10);
// 缓冲执行任务的队列50
executor.setQueueCapacity(50);
// 线程的空闲时间60秒
executor.setKeepAliveSeconds(60);
// 线程池对拒绝任务的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 线程池关闭的时等待所有任务都完成再继续销毁其他的Bean
executor.setWaitForTasksToCompleteOnShutdown(true);
// 设置线程池中任务的等待时间
executor.setAwaitTerminationSeconds(300);
return executor;
}
}
1.3 输出信息
从输出的日志信息中可以发现,两个异步方法所使用的线程池不一样,asyncJob
采用默认的cTaskExecutor
线程池,asyncJobPool
方法采用的是async-pool
线程池;
[schedule-pool-1] c.boot.senior.schedule.ScheduleService : async-job-02-end...
[cTaskExecutor-1] c.boot.senior.schedule.ScheduleService : async-job-01-end...
2、调度任务
2.1 调度配置
通过实现SchedulingConfigurer
接口,来修改调度任务的配置,这里重新定义任务执行的线程池;
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
2.2 调度方法
通过Scheduled
注解来标记方法,基于定时器的规则设定,来统一管理方法的执行时间;
@Component
public class ScheduleJob {
private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class);
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
/**
* 上一次开始执行时间点之后10秒再执行
*/
@Scheduled(fixedRate = 10000)
private void timerJob1(){
log.info("timer-job-1:{}",format.format(new Date()));
}
/**
* 上一次执行完毕时间点之后10秒再执行
*/
@Scheduled(fixedDelay = 10000)
private void timerJob2(){
log.info("timer-job-2:{}",format.format(new Date()));
}
/**
* Cron表达式:每30秒执行一次
*/
@Scheduled(cron = "0/30 * * * * ?")
private void timerJob3(){
log.info("timer-job-3:{}",format.format(new Date()));
}
}
五、邮件发送
1、邮件配置
采用QQ
邮箱来模拟邮件的发送方,需要先开启smtp
邮件传输协议,在QQ
邮箱的设置/账户路径下,并且获取相应的授权码,在项目的配置中使用;
spring:
application:
name: boot-senior
# 邮件配置
mail:
host: smtp.qq.com
port: 465
protocol: smtps
username: 邮箱账号
password: 邮箱授权码
properties:
mail.smtp.ssl.enable: true
2、方法封装
定义一个简单的邮件发送方法,并且可以添加附件,是常用的功能之一;另外也可以通过Html静态页渲染,再转换为邮件内容的方式;
@Service
public class SendMailService {
@Value("${spring.mail.username}")
private String userName ;
@Resource
private JavaMailSender sender;
/**
* 带附件的邮件发送方法
* @param toUsers 接收人
* @param subject 主题
* @param content 内容
* @param attachPath 附件地址
* @return java.lang.String
* @since 2023-07-10 17:03
*/
public String sendMail (String[] toUsers,String subject,
String content,String attachPath) throws Exception {
// MIME邮件类
MimeMessage mimeMessage = sender.createMimeMessage();
MimeMessageHelper helper = ne