Spring邮件抽象层.docx
《Spring邮件抽象层.docx》由会员分享,可在线阅读,更多相关《Spring邮件抽象层.docx(9页珍藏版)》请在冰豆网上搜索。
![Spring邮件抽象层.docx](https://file1.bdocx.com/fileroot1/2022-12/16/6092a819-e2be-498e-ac7e-afc94463a97b/6092a819-e2be-498e-ac7e-afc94463a97b1.gif)
Spring邮件抽象层
Spring邮件抽象层
22.1. 简介
资源类库依赖
下面所列出的jar文件必须加到你应用程序的classpath中,因为这些都是SpringFramework邮件抽象层所依赖的库文件。
∙JavaMailmail.jar库
∙JAFactivation.jar库
所有这些依赖的库都可以在SpringFramework的Spring-with-dependencies的release包中获得(同时也可以在网上免费获得)。
Spring提供了一个发送电子邮件的高级抽象层,它向用户屏蔽了底层邮件系统的一些细节,同时代表客户端负责底层的资源处理。
Spring邮件抽象层的主要包为org.springframework.mail。
它包括了发送电子邮件的主要接口MailSender,和值对象SimpleMailMessage,它封装了简单邮件的属性如from,to,cc,subject,text。
包里还包含一棵以MailException为根的checkedException继承树,它们提供了对底层邮件系统异常的高级别抽象。
要获得关于邮件异常层次的更丰富的信息,请参考Javadocs。
为了使用JavaMail中的一些特色,比如MIME类型的信件,Spring提供了MailSender的一个子接口,即org.springframework.mail.javamail.JavaMailSender。
Spring还提供了一个回调接口org.springframework.mail.javamail.MimeMessagePreparator,用于准备JavaMail的MIME信件。
22.2. 使用Spring邮件抽象
假设某个业务接口名为OrderManager:
publicinterfaceOrderManager{
voidplaceOrder(Orderorder);
}
我们同时假设有一个用例:
需要生成带有订单号的email信件,并向客户发送该订单。
22.2.1. MailSender和SimpleMailMessage的基本用法
importorg.springframework.mail.MailException;
importorg.springframework.mail.MailSender;
importorg.springframework.mail.SimpleMailMessage;
publicclassSimpleOrderManagerimplementsOrderManager{
privateMailSendermailSender;
privateSimpleMailMessagetemplateMessage;
publicvoidsetMailSender(MailSendermailSender){
this.mailSender=mailSender;
}
publicvoidsetTemplateMessage(SimpleMailMessagetemplateMessage){
this.templateMessage=templateMessage;
}
publicvoidplaceOrder(Orderorder){
//Dothebusinesscalculations...
//Callthecollaboratorstopersisttheorder...
//Createathreadsafe"copy"ofthetemplatemessageandcustomizeit
SimpleMailMessagemsg=newSimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear"+order.getCustomer().getFirstName()
+order.getCustomer().getLastName()
+",thankyouforplacingorder.Yourordernumberis"
+order.getOrderNumber());
try{
this.mailSender.send(msg);
}
catch(MailExceptionex){
//simplylogitandgoon...
System.err.println(ex.getMessage());
}
}
}
上面的代码的bean定义应该是这样的:
--thisisatemplatemessagethatwecanpre-loadwithdefaultstate-->
22.2.2. 使用JavaMailSender和MimeMessagePreparator
下面是OrderManager的另一种实现,使用了MimeMessagePreparator回调接口。
请注意在这个用例中,mailSender属性是JavaMailSender类型,所以我们可以使用JavaMail的MimeMessage类:
importjavax.mail.Message;
importjavax.mail.MessagingException;
importjavax.mail.internet.InternetAddress;
importjavax.mail.internet.MimeMessage;
importjavax.mail.internet.MimeMessage;
importorg.springframework.mail.MailException;
importorg.springframework.mail.javamail.JavaMailSender;
importorg.springframework.mail.javamail.MimeMessagePreparator;
publicclassSimpleOrderManagerimplementsOrderManager{
privateJavaMailSendermailSender;
publicvoidsetMailSender(JavaMailSendermailSender){
this.mailSender=mailSender;
}
publicvoidplaceOrder(finalOrderorder){
//Dothebusinesscalculations...
//Callthecollaboratorstopersisttheorder...
MimeMessagePreparatorpreparator=newMimeMessagePreparator(){
publicvoidprepare(MimeMessagemimeMessage)throwsException{
mimeMessage.setRecipient(Message.RecipientType.TO,
newInternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(newInternetAddress("mail@"));
mimeMessage.setText(
"Dear"+order.getCustomer().getFirstName()+""
+order.getCustomer().getLastName()
+",thankyouforplacingorder.Yourordernumberis"
+order.getOrderNumber());
}
};
try{
this.mailSender.send(preparator);
}
catch(MailExceptionex){
//simplylogitandgoon...
System.err.println(ex.getMessage());
}
}
}
Note
以上的邮件代码是一个横切关注点,能被完美地重构为自定义SpringAOP切面的候选者,这样它就可以在目标对象OrderManager的一些合适的连接点(joinpoint)中被执行了。
SpringFramework的邮件支持直接提供两种MailSender的实现。
标准的JavaMail实现和基于JasonHunter编写的MailMessage类之上的实现,后者位于com.oreilly.servlet包中。
请查阅相关Javadocs以获得进一步的资料。
22.3. 使用MimeMessageHelper
org.springframework.mail.javamail.MimeMessageHelper是处理JavaMail邮件时比较顺手组件之一。
它可以让你摆脱繁复的JavaMailAPI。
通过使用MimeMessageHelper,创建一个MimeMessage实例将非常容易:
//ofcourseyouwoulduseDIinanyreal-worldcases
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("");
MimeMessagemessage=sender.createMimeMessage();
MimeMessageHelperhelper=newMimeMessageHelper(message);
helper.setTo("test@");
helper.setText("Thankyouforordering!
");
sender.send(message);
22.3.1. 发送附件和嵌入式资源(inlineresources)
Multipartemail允许添加附件和内嵌资源(inlineresources)。
内嵌资源可能是你在信件中希望使用的图像或样式表,但是又不想把它们作为附件。
22.3.1.1. 附件
下面的例子将展示如何使用MimeMessageHelper来发送一封email,使用一个简单的JPEG图片作为附件:
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("");
MimeMessagemessage=sender.createMimeMessage();
//usethetrueflagtoindicateyouneedamultipartmessage
MimeMessageHelperhelper=newMimeMessageHelper(message,true);
helper.setTo("test@");
helper.setText("Checkoutthisimage!
");
//let'sattachtheinfamouswindowsSamplefile(thistimecopiedtoc:
/)
FileSystemResourcefile=newFileSystemResource(newFile("c:
/Sample.jpg"));
helper.addAttachment("CoolImage.jpg",file);
sender.send(message);
22.3.1.2. 内嵌资源
下面的例子将展示如何使用MimeMessageHelper来发送一封含有内嵌资源的email:
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("");
MimeMessagemessage=sender.createMimeMessage();
//usethetrueflagtoindicateyouneedamultipartmessage
MimeMessageHelperhelper=newMimeMessageHelper(message,true);
helper.setTo("test@");
//usethetrueflagtoindicatethetextincludedisHTML
helper.setText("
identifier1234'>",true);
//let'sincludetheinfamouswindowsSamplefile(thistimecopiedtoc:
/)
FileSystemResourceres=newFileSystemResource(newFile("c:
/Sample.jpg"));
helper.addInline("identifier1234",res);
sender.send(message);
Warning
如你所见,嵌入式资源使用Content-ID(上例中是identifier1234)来插入到mime信件中去。
你加入文本和资源的顺序是非常重要的。
首先,你加入文本,随后是资源。
如果顺序弄反了,它将无法正常运作!
22.3.2. 使用模板来创建邮件内容
在之前的代码示例中,所有邮件的内容都是显式定义的,并通过调用message.setText(..)来设置邮件内容。
这种做法针对简单的情况或在上述的例子中没什么问题,因为在这里只是为了向你展示基础API。
而在你自己的企业级应用程序中,基于如下的原因,你不会以上述方式创建你的邮件内容:
∙使用Java代码来创建基于HTML的邮件内容不仅容易犯错,同时也是一件单调乏味的事情
∙这样做,你将无法将显示逻辑和业务逻辑很明确的区分开
∙一旦需要修改邮件内容的显式格式和内容,你需要重新编写Java代码,重新编译,重新部署……
一般来说解决这些问题的典型的方式是使用FreeMarker或者Velocity这样的模板语言来定义邮件内容的显式结构。
这样,你的任务就是在你的代码中,只要创建在邮件模板中需要展示的数据,并发送邮件即可。
通过使用Spring对FreeMarker和Velocity的支持类,你的邮件内容将变得简单,这同时也是一个最佳实践。
下面是一个使用Velocity来创建邮件内容的例子:
22.3.2.1. 一个基于Velocity的示例
使用Velocity来创建你的邮件模板,你需要把Velocity加入到classpath中。
同时要根据应用的需要为邮件内容创建一个或者多个Velocity模板。
下面的Velocity模板是这个例子中所使用的基于HTML的模板。
这只是一个普通的文本,你可以通过各种其他的编辑器来编辑该文本,而无需了解Java方面的知识。
#inthecom/foo/package
Hi${user.userName},welcometotheChippingSodburyOn-the-Hillmessageboards!
Youremailaddressis${user.emailAddress}">${user.emailAddress}.
下面提供了一些简单的代码与SpringXML配置,它们使用了上述Velocity模板来创建邮件内容并发送邮件。
packagecom.foo;
importorg.apache.velocity.app.VelocityEngine;
importorg.springframework.mail.javamail.JavaMailSender;
importorg.springframework.mail.javamail.MimeMessageHelper;
importorg.springframework.mail.javamail.MimeMessagePreparator;
importorg.springframework.ui.velocity.VelocityEngineUtils;
importjavax.mail.internet.MimeMessage;
importjava.util.HashMap;
importjava.util.Map;
publicclassSimpleRegistrationServiceimplementsRegistrationService{
privateJavaMailSendermailSender;
privateVelocityEnginevelocityEngine;
publicvoidsetMailSender(JavaMailSendermailSender){
this.mailSender=mailSender;
}
publicvoidsetVelocityEngine(VelocityEnginevelocityEngine){
this.velocityEngine=velocityEngine;
}
publicvoidregister(Useruser){
//Dotheregistrationlogic...
sendConfirmationEmail(user);
}
privatevoidsendConfirmationEmail(finalUseruser){
MimeMessagePreparatorpreparator=newMimeMessagePreparator(){
publicvoidprepare(MimeMessagemimeMessage)throwsException{
MimeMessageHelpermessage=newMimeMessageHelper(mimeMessage);
message.setTo(user.getEmailAddress());
message.setFrom("webmaster@csonth.gov.uk");//couldbeparameterized...
Mapmodel=newHashMap();
model.put("user",user);
Stringtext=VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine,"com/dns/registration-confirmation.vm",model);
message.setText(text,true);
}
};
this.mailSender.send(preparator);
}
}
xmlversion="1.0"encoding="UTF-8"?
>
//www.springframework.org/schema/beans"
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="http:
//www.springframework.org/schema/beans
http:
//www.springframework.org/schema/beans/spring-beans-2.5.xsd">
resource.loader=class
class.resou