1. 异步任务(@EnableAsync+@Async)
- 与传统的同步编码不同,异步调用会新建一个线程,与请求线程并行。如不做特殊的处理,请求线程将会继续向下执行。
- @Async的作用:当在请求线程中调用到被标注的方法时,Spring将自动创建一个线程池来运行这个方法,请求线程不会阻塞,继续向下执行。(也就是代替了手动编写的多线程)
- 实例
(1)给需要异步执行的方法标注@Aysnc。@Service public class AsyncService { //说明这是一个异步方法 @Async public void hello(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("数据处理中..."); } }
(2)在主配置类上标注@EnableAsyc,开启基于注解的异步任务功能。
2. 定时任务(@Scheduled+@EnableScheduling)
-
Spring提供了TaskExecutor和TaskScheduler接口支持异步执行任务调度的方式。
-
实例
(1)给需要定时执行的方法上标注@Scheduled,指定合适的cron表达式。@Service public class ScheduledService { //一个cron表达式由6个域构成,它们之间靠空格划分,分别是: //second,minute,hour,day of month,month,day of week //0 * * * * * MON-FRI 表示从周一到周五每分钟的0秒(如14:18:00)启动一次 @Scheduled(cron = "0 * * * * * MON-FRI") public void sayHelloOnTime(){ System.out.println("hello,"+System.currentTimeMillis()); } }
(2) 在主配置类上标注@EnableScheduling,开启基于注解的定时任务功能。
-
cron表达式
字段 允许的具体值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 时 0-23 , - * / 天,日期 1-31 , - ? / L W C 月 1-12 , - * / 天,星期 0-7或SUN-SAT,注意0和7都是SUNDAY,1-6是MONDY-SATURDAY , * ? / L C # 特殊字符 代表含义 , 枚举,分隔所列出的多个启动具体时间值 - 区间,一段时间 * 任意 /x 步长,每隔x单位执行一次 ? 日期与星期冲突匹配时使用 L 最后 W 工作日 C 和Calendar联系后计算过的值 # 第几个星期几,如4#2表示第2个星期4 【举例】
#每分钟的第0、1、2、3、4秒都会运行一次 0,1,2,3,4 * * * * * 0-4 * * * * * #每4秒运行一次 0/4 * * * * * #每天14点和18点整,每隔5分钟运行一次 0 0/5 14,18 * * ? #每个月的周一至周六10:15分运行一次 0 15 10 ? * 1-6 #每个月的最后一个周六的凌晨2点运行一次 0 0 2 ? * 6L #每个月的最后一个工作日凌晨2点执行一次 0 0 2 LW * ? #每个月的第一个周一凌晨2-4点期间,每个整点都执行一次 #0 0 2-4 ? * 1#1
3. 邮件任务
3.1 在Spring Boot中使用JavaMail
- 导入spring-boot-starter-mail依赖。
<!-- 它引入javax.mail包,java对邮件的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
- 在主配置文件中配置发送邮件需要的信息。
spring.mail.username=xxx #市面上现存的邮箱产品,出于安全考虑,需要使用一个授权码作为第三方登录邮件服务器的独立密码。(授权码在邮箱的“账户设置”选项中可以生成) spring.mail.password=iuosjsaxuwqllpvb #protocol默认是SMTP协议,所以要设置SMTP邮件服务器地址 spring.mail.host=smtp.qq.com #发送时报530错误(A secure connection is required such as ssl)的解决方法:开启ssl #额外的配置都写在mail.properties中,它底层是一个HashMap<String,String> spring.mail.properties.mail.smtp.ssl.enable=true
- 在测试类中注入JavaMailSender,调用其方法进行测试。
@Autowired JavaMailSenderImpl javaMailSender; //发送简单邮件 @Test void sendSimple() { SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); //设置邮件信息 simpleMailMessage.setSubject("setSubject设置邮件题目"); simpleMailMessage.setText("setText设置邮件文本内容"); //可以发送给多人 simpleMailMessage.setTo("firstreceiver@163.com","secondreceiver@gmail.com"); //设置发件人 simpleMailMessage.setFrom("xxx@qq.com"); javaMailSender.send(simpleMailMessage); } //发送复杂邮件:带附件,内容是html等等 @Test void sendMime() throws Exception{ //1. 创建一个复杂的消息邮件MimeMessage MimeMessage mimeMessage = javaMailSender.createMimeMessage(); //2. 创建一个MimeMessageHelp并装入前面创建的MimeMessage,简化MimeMessage的信息设置 //第二个参数,true表示开启multipart(上传文件的支持) MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); mimeMessageHelper.setSubject("setSubject设置邮件题目"); //第二个参数,true表示开启对html内容的支持 mimeMessageHelper.setText("<h1 style='color:red'>setText设置邮件文本内容</h1>",true); mimeMessageHelper.setTo("firstreceiver@163.com"); mimeMessageHelper.setFrom("xxx@qq.com"); //上传附件,支持上传多个附件 mimeMessageHelper.addAttachment("这是在邮件中的名字1",new File("附件在磁盘上的路径1")); mimeMessageHelper.addAttachment("这是在邮件中的名字2",new File("附件在磁盘上的路径2")); //3.发送MimeMessage本体 javaMailSender.send(mimeMessage); }
3.2 JavaMail的自动配置原理(MailSenderAutoConfiguration+MailProperties)
-
MailSenderAutoConfiguration,通过@Import(MailSenderPropertiesConfiguration)向容器中注入MailSenderPropertiesConfiguration,而且由它给组件注入了JavaMailSenderImpl作为容器中默认的MailSender实现,由它来发送邮件。
@Bean @ConditionalOnMissingBean({JavaMailSender.class}) JavaMailSenderImpl mailSender(MailProperties properties) { JavaMailSenderImpl sender = new JavaMailSenderImpl(); this.applyProperties(properties, sender); return sender; }
-
MailProperties
@ConfigurationProperties( prefix = "spring.mail" ) public class MailProperties { private static final Charset DEFAULT_CHARSET; private String host; private Integer port; private String username; private String password; private String protocol = "smtp"; private Charset defaultEncoding; private Map<String, String> properties; private String jndiName; //... ... }