本文借助Spring对消息功能的支持,以排队任务形式异步发送Spittle
提醒给Spittr
的其他用户。Spring是怎么样抽象邮件发送这一问题,然后利用这一抽象发送包含Spittle提醒Email消息。
配置Spring发送邮件
Spring Email抽象的核心是MailSender
接口。顾名思义。MailSender
的实现能够通过连接Email服务器实现邮件发送的功能。
Spring的MailSender接口是Spring Email抽象API的核心组件。他把Email发送给邮件服务器,由服务器进行邮件投递。
Spring自带的一个MailSender
的实现也就是JavaMailSenderImpl
,它会使用JavaMail API
来发送Email。Spring应用在发送Email之前,我们必须要将JavaMailSenderImpl
来装配为Spring应用上下文的一个bean。
配置邮件发送器
按照最简单的形式,我们只需在@Bean
方法中使用几行代码就能将JavaMailSenderImpl
配置为一个bean
:
@Bean
public MailSender mailSender(Environment env) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(env.getProperty("mailserver.host"));
return mailSender;
}
属性host是可选的(它默认是底层JavaMail会话的主机),但你可能希望设置该属性。它指定了要用来发送Email的邮件服务器主机名,按照这个配置,会从注入的Environment
中获取值,这样我们就能在Spring之外管理邮件服务器的配置(比如在属性文件中)。
默认情况下,JavaMailSenderImpl
假设邮件服务器监听25号端口(标准的SMTP端口)。如果你的邮件服务器监听不同的端口,那么可以使用port属性指定正确的端口号。例如:
@Bean
public MailSender mailSender(Environment env) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(env.getProperty("mailserver.host"));
mailSender.setPort(env.getProperty("mailserver.Port"));
return mailSender;
}
类似的,如果邮件服务器需要认证的话,你还需要设置username和password属性:
@Bean
public MailSender mailSender(Environment env) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(env.getProperty("mailserver.host"));
mailSender.setPort(env.getProperty("mailserver.Port"));
mailSender.setUsername(env.getProperty("mailserver.username"));
mailSender.setPassword(env.getProperty("mailserver.password"));
return mailSender;
}
到目前为止,JavaMailSenderImpl
已经配置完成,它可以创建自己的邮件会话,但是你可能已经在JNDI
中配置了javax.mail.MailSession
(也可能是你的应用服务器放在哪里的)。如果这样的话。那就没有必要为JavaMailSenderImpl
配置详细的服务器细节了。我们可以配置它使用JNDI
中已经就绪的MailSession
。
借助JndiObjectFactoryBean,我们可以在如下的@Bean方法中配置一个Bean,它会从JDNI中查找MailSession:
@Bean
public JndiObjectFactoryBean mailSession() {
JndiObjectFactoryBean jndi = new JndiObjectFactoryBean();
jndi.SetJndiName("mail/Session");
jndi.SetProxyInterface(MailSession.class);
jndi.serResourceRef(true);
return jndi;
}
我们已经看到过如何使用Spring的<jee:jndi-lookup>
,元素从JNDI中获取对象,这里可以使用<jee:jndi-lookup>
来创建一个bean,它引用了JNDI中的邮件会话:
<jee:jndi-lookup id = "mailSession" jndi-name="mail/Session" resource-ref="true" />
邮件会话准备就绪后可以,将其装配到mailSender bean 中:
@Bean
public MailSender mailSender(MailSession mailSession) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setSession(mailSession);
return mailSender;
}
装配和使用邮件发送器
在Spittr应用程序中,最适合发送Email的是SpitterEmailServiceImpl
类。这个类有一个mailSender属性,它使用了@Autowired注解:
@Autowired
JavaMailSender mailSender;
当Spring将SpitterEmailServiceImpl
创建为一个bean的时候,它将查找实现了MailSender的bean。这样的bean可以装配到mailSender属性中。
使用Spring的MailSender发送Email:
@Override
public void sendSimpleSpittleEmail(String to, Spittle spittle) {
SimpleMailMessage message = new SimpleMailMessage();
String spitterName = spittle.getSpitter().getFullName();
message.setFrom("noreply@spitter.com");
message.setTo(to);
message.setSubject("New spittle from " + spitterName);
message.setText(spitterName + " says: " + spittle.getText());
mailSender.send(message);
}