利用Spring框架封裝的JavaMail現(xiàn)實同步或異步郵件發(fā)送
作者:張紀豪
J2EE簡單地講是在JDK上擴展了各類應用的標準規(guī)范,郵件處理便是其中一個重要的應用,。它既然是規(guī)范,那么我們就可以通過JDK遵照郵件協(xié)議編寫一個郵件處理系統(tǒng),,但事實上已經有很多廠商和開源組織這樣做了,。Apache是J2EE最積極的實現(xiàn)者之一,當然還有我們的老大——SUN,。
聊起老大,,感慨萬端!他已經加入Oracle——甲骨文(不是刻在烏龜殼上的那種文字嗎,?是我中華,,也是人類上最早的語言啊,比Java早幾千年哦),,其掌門人拉里·埃里森是個不錯的水手,,別以為那只是在帆船上,至少他不至于蓋茨那么不仁道——開源萬歲,。有理由相信Java世界還有一段輝煌的歷程,。Google的Android和Chrome OS兩大操作系統(tǒng),還會首選Java作應用開發(fā)基礎語言,,即便是推出自己的易語言,。同時筆者預感到ChromeOS前景不可估量,它可能是推動云計算一個重要組成部分,,Andtroid(主用在移動設備上,,未來可能是手機上主流的操作系統(tǒng)),乃至微軟的Windows將來可能都是該系統(tǒng)的小窗口而已,。微軟已顯得老態(tài)龍鐘了,,再與大勢已去的雅虎合作,前進步伐必將大大減緩,。投資者此時可以長線買入Google股票(投資建議,,必自判斷),。筆者也常用google搜索引擎、gmail,。
好了,,閑話少聊,言歸主題,。
可能大家如筆者一樣用的最多的是老大的javamail,,雖然老大實現(xiàn)了郵件功能,但調用起來還是需要較復雜的代碼來完成,,而且初學者調用成功率很低(因為它還要與外界服務器通信),,這就使得初學者對于它越學越迷茫。不過這方面的例子很多,,因此筆者不再在此重復這些示例代碼,,而著重利用Spring框架封裝的郵件處理功能。
開工之前,,我們先了解下環(huán)境,。筆者開的是web工程,所需要的基礎配置如下:
▲ JDK 1.6
▲ J2EE 1.5
▲ JavaMail 1.4 稍作說明:J2EE 1.5中已經納入了郵件規(guī)范,,因此在開發(fā)期不要導入javamail中的jar包,,運行期則需要,因此可以將jar包放入到web容器的java庫中(例如Tomcat的lib目錄下),,要了解其意可以參考數(shù)據(jù)庫驅動包的運用,。文章結尾會對其進一步說明;
▲ Spring 2.5
▲ 一個郵箱 如上所述,,筆者愛用Google的Gmail郵箱,。
主要文件清單:
■ MailService.java 郵件處理對象接口
■ MailServiceImpl.java 上述實現(xiàn)
■ Email.java 一個普通的JavaBean,用于封裝郵件數(shù)據(jù),,并與html頁面中form表單對應
■ MailController.java 動作處理器
■ spring-core-config.xml Spring核心配置
筆者的web工程中,,WEB層使用的是Spring @MVC,當然我們僅需要了解其原理,,利用servlet或struts框架來做web層動作處理器都能實現(xiàn),。其它的文件,例如web.xml,,WEB層配置均略,。
下面開始代碼:
spring-core-config.xml:
- <!--①郵件服務器-->
- <beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">
- <propertyname="protocol"value="smtp"/>
- <propertyname="host"value="smtp.gmail.com"/>
- <propertyname="port"value="465"/><!--Gmail的SMTP端口居然是這個,去google網站上了解吧-->
- <propertyname="username"value="到google注冊一個gmail賬戶"/>
- <propertyname="password"value="這里是密碼"/>
- <propertyname="javaMailProperties">
- <props>
- <propkey="mail.smtp.auth">true</prop>
- <propkey="mail.smtp.starttls.enable">true</prop>
- <propkey="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop><!--gmail要求的ssl連接-->
- </props>
- </property>
- </bean>
- <!--②異步線程執(zhí)行器-->
- <beanid="taskExecutor"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
- <propertyname="corePoolSize"value="10"/>
- <propertyname="maxPoolSize"value="30"/>
- </bean>
- <!--①郵件服務器-->
- <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
- <property name="protocol" value="smtp"/>
- <property name="host" value="smtp.gmail.com"/>
- <property name="port" value="465" /><!--Gmail的SMTP端口居然是這個,,去google網站上了解吧-->
- <property name="username" value="到google注冊一個gmail賬戶"/>
- <property name="password" value="這里是密碼"/>
- <property name="javaMailProperties">
- <props>
- <prop key="mail.smtp.auth">true</prop>
- <prop key="mail.smtp.starttls.enable">true</prop>
- <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> <!--gmail要求的ssl連接-->
- </props>
- </property>
- </bean>
-
- <!--②異步線程執(zhí)行器-->
- <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
- <property name="corePoolSize" value="10"/>
- <property name="maxPoolSize" value="30"/>
- </bean>
這是郵件處理的兩個核心配置,,第一個配置(①)是往容器中裝配一個JavaMailSender Bean,它就是JavaMail的封裝,其中最關鍵的是裝配過程的屬性參數(shù),,這些屬性既要嚴格遵照JavaMail規(guī)范,,又要滿足郵件提供商的要求,例如SMTP服務器端口是多少,、發(fā)送時是否要身份驗證,、服務器是否采用安全連接、連接時是否加密以及采用什么樣的加密方式,,郵件服務商提供的這些參數(shù)直接影響到上述的配置,,這往往是新手最容易忽視的環(huán)節(jié),因此配置之前一定要到郵件提供商的站點上詳細了解郵箱的技術參數(shù),。
同步異步發(fā)送問題:JavaMail郵件處理是同步的,,即用戶觸發(fā)事件、與SMTP Server通信,、服務器返回狀態(tài)消息,、程序結束是單線程內,這時往往因Socket通信,、服務器業(yè)務處理速度等原因而使得處理時間是個未知數(shù),。舉個簡單的應用實例:若用戶在提交注冊的同時發(fā)送一封激活賬戶郵件,用戶有可能不知道是因為郵件服務器那兒阻塞致半天沒有反應而以為注冊失敗并放棄,,這將是失敗的設計,但異步方式能解決這些問題,。異步方式簡單地說就是將郵件處理任務交給另外一個線程,,J2EE有兩種解決方案,一是種利用JMS,,JMS可以實現(xiàn)同步和異步的消息處理,,將郵件作為一個異步的消息,就可以實現(xiàn)異步郵件發(fā)送,。JMS屬于J2EE的高級應用,,所以對于僅以WEB功能的容器還不支持這種服務,例如Tomcat(當然可以找到插件來解決),,由于篇幅限制,,本文不再牽涉到新的模塊。另一種方案是利用JDK中Executor的支持,,JDK
5.0后繼版本增加了java.util.concurrent一個強大的并發(fā)工具包,,它包含了執(zhí)行器、計時器,、鎖,、線程安全隊列、線程任務框架等等。Executor——執(zhí)行器,,它可以將任務的“提交”與“執(zhí)行”分離解耦,,我們的郵件處理任務完全可以借用它實現(xiàn)異步執(zhí)行。而Spring框架提供了封裝,,見②,。下面我們來看如何使用它,代碼如下,。
MailServiceImpl.java :
- package com.zhangjihao.service.impl;
- import java.io.IOException;
- import javax.annotation.Resource;
- import javax.mail.MessagingException;
- import javax.mail.internet.MimeMessage;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.core.io.ByteArrayResource;
- import org.springframework.core.task.TaskExecutor;
- import org.springframework.mail.javamail.JavaMailSender;
- import org.springframework.mail.javamail.MimeMessageHelper;
- import org.springframework.stereotype.Service;
- import org.springframework.web.multipart.MultipartFile;
- import com.zhangjihao.bean.Email;
- import com.zhangjihao.service.MailService;
- import com.zhangjihao.util.StringUtil;
- /**
- * 說明:<br>
- * * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
- @Service("mailService")
- public class MailServiceImplimplements MailService {
- @Resource JavaMailSender mailSender;//注入Spring封裝的javamail,,Spring的xml中已讓框架裝配
- @Resource TaskExecutor taskExecutor;//注入Spring封裝的異步執(zhí)行器 private Log log = LogFactory.getLog(getClass());
- private StringBuffer message =new StringBuffer();
- public void sendMail(Email email)throws MessagingException, IOException {
- if(email.getAddress() ==
null || email.getAddress().length == 0) {
- this.message.append("沒有收件人");
- return;
- }
- if(email.getAddress().length >5){//收件人大于5封時,采用異步發(fā)送 sendMailByAsynchronousMode(email);
- this.message.append("收件人過多,,正在采用異步方式發(fā)送...<br/>");
- }else{
- sendMailBySynchronizationMode(email);
- this.message.append("正在同步方式發(fā)送郵件...<br/>");
- }
- }
- /**
- * 異步發(fā)送
- * @see com.zhangjihao.service.MailService#sendMailByAsynchronousMode(com.zhangjihao.bean.Email)
- */
- public void sendMailByAsynchronousMode(final Email email){ taskExecutor.execute(new
Runnable(){
- public void run(){
- try {
- sendMailBySynchronizationMode(email);
- } catch (Exception e) {
- log.info(e);
- }
- }
- });
- }
- /**
- * 同步發(fā)送
- * @throws IOException
- * @see com.zhangjihao.service.MailServiceMode#sendMail(com.zhangjihao.bean.Email)
- */
- public void sendMailBySynchronizationMode(Email email)throws MessagingException, IOException {
- MimeMessage mime = mailSender.createMimeMessage(); MimeMessageHelper helper =new MimeMessageHelper(mime,
true,"utf-8");
- helper.setFrom("[email protected]");//發(fā)件人
- helper.setTo(email.getAddress());//收件人
- helper.setBcc("[email protected]");//暗送
- if(StringUtil.hasLength(email.getCc())){
- String cc[] = email.getCc().split(";");
- helper.setCc(cc);//抄送
- }
- helper.setReplyTo("[email protected]");//回復到
- helper.setSubject(email.getSubject());//郵件主題
- helper.setText(email.getContent(), true);//true表示設定html格式
- //內嵌資源,,這種功能很少用,因為大部分資源都在網上,,只需在郵件正文中給個URL就足夠了.
- //helper.addInline("logo", new ClassPathResource("logo.gif")); //處理附件
- for(MultipartFile file : email.getAttachment()){
- if(file == null || file.isEmpty()){
- continue;
- }
- String fileName = file.getOriginalFilename();
- try {
- fileName = new String(fileName.getBytes("utf-8"),"ISO-8859-1");
- } catch (Exception e) {
- }
- helper.addAttachment(fileName, new ByteArrayResource(file.getBytes()));
- }
- mailSender.send(mime);
- }
- public StringBuffer getMessage() {return message; }
- public void setMessage(StringBuffer message) {this.message = message; }}
- package com.zhangjihao.service.impl;
-
- import java.io.IOException;
- import javax.annotation.Resource;
- import javax.mail.MessagingException;
- import javax.mail.internet.MimeMessage;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.core.io.ByteArrayResource;
- import org.springframework.core.task.TaskExecutor;
- import org.springframework.mail.javamail.JavaMailSender;
- import org.springframework.mail.javamail.MimeMessageHelper;
- import org.springframework.stereotype.Service;
- import org.springframework.web.multipart.MultipartFile;
- import com.zhangjihao.bean.Email;
- import com.zhangjihao.service.MailService;
- import com.zhangjihao.util.StringUtil;
- /**
- * 說明:<br>
- * * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
-
- @Service("mailService")
- public class MailServiceImpl implements MailService {
- @Resource JavaMailSender mailSender;//注入Spring封裝的javamail,,Spring的xml中已讓框架裝配
- @Resource TaskExecutor taskExecutor;//注入Spring封裝的異步執(zhí)行器 private Log log = LogFactory.getLog(getClass());
- private StringBuffer message = new StringBuffer();
- public void sendMail(Email email) throws MessagingException, IOException {
- if(email.getAddress() == null || email.getAddress().length == 0) {
- this.message.append("沒有收件人");
- return;
- }
- if(email.getAddress().length > 5){//收件人大于5封時,采用異步發(fā)送 sendMailByAsynchronousMode(email);
- this.message.append("收件人過多,,正在采用異步方式發(fā)送...<br/>");
- }else{
- sendMailBySynchronizationMode(email);
- this.message.append("正在同步方式發(fā)送郵件...<br/>");
- }
- }
- /**
- * 異步發(fā)送
- * @see com.zhangjihao.service.MailService#sendMailByAsynchronousMode(com.zhangjihao.bean.Email)
- */
- public void sendMailByAsynchronousMode(final Email email){ taskExecutor.execute(new Runnable(){
- public void run(){
- try {
- sendMailBySynchronizationMode(email);
- } catch (Exception e) {
- log.info(e);
- }
- }
- });
- }
-
- /**
- * 同步發(fā)送
- * @throws IOException
- * @see com.zhangjihao.service.MailServiceMode#sendMail(com.zhangjihao.bean.Email)
- */
-
- public void sendMailBySynchronizationMode(Email email) throws MessagingException, IOException {
- MimeMessage mime = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mime, true, "utf-8");
- helper.setFrom("[email protected]");//發(fā)件人
- helper.setTo(email.getAddress());//收件人
- helper.setBcc("[email protected]");//暗送
- if(StringUtil.hasLength(email.getCc())){
- String cc[] = email.getCc().split(";");
- helper.setCc(cc);//抄送
- }
- helper.setReplyTo("[email protected]");//回復到
- helper.setSubject(email.getSubject());//郵件主題
- helper.setText(email.getContent(), true);//true表示設定html格式
- //內嵌資源,,這種功能很少用,因為大部分資源都在網上,,只需在郵件正文中給個URL就足夠了.
- //helper.addInline("logo", new ClassPathResource("logo.gif")); //處理附件
- for(MultipartFile file : email.getAttachment()){
- if(file == null || file.isEmpty()){
- continue;
- }
- String fileName = file.getOriginalFilename();
- try {
- fileName = new String(fileName.getBytes("utf-8"),"ISO-8859-1");
- } catch (Exception e) {
- }
- helper.addAttachment(fileName, new ByteArrayResource(file.getBytes()));
- }
- mailSender.send(mime);
- }
- public StringBuffer getMessage() { return message; }
- public void setMessage(StringBuffer message) { this.message = message; }}
此類實現(xiàn)了MailService接口,,該接口僅三個方法(接口文件代碼省略):一個發(fā)送分流器、一個同步發(fā)送方法,、一個異步發(fā)送方法,。通過其實現(xiàn)者MailServiceImpl的代碼可以看出,郵件發(fā)送僅在同步發(fā)送這個方法中,,當需要異步執(zhí)行的時候,,只需要將其扔進taskExecutor異步執(zhí)行器中,就這么簡單,。這三個方法都是public修飾的,,所以在上層隨意調用哪個都行。以下看一個簡單的調用代碼,。
調用之前,,為讓初學者能更好地接受,先列出Email.java代碼:
Email.java:
- package com.zhangjihao.bean;
- import java.io.Serializable;
- import org.springframework.web.multipart.MultipartFile;
- import com.zhangjihao.util.StringUtil;
- /**
- * 說明:<br>
- *
- * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
- public class Emailimplements Serializable {
- private staticfinal
long serialVersionUID = 9063903350324510652L;
- /**用戶組:可以按用戶組來批量發(fā)送郵件**/
- private UserGroups userGroups;
- /**收件人**/
- private String addressee;
- /**抄送給**/
- private String cc;
- /**郵件主題**/
- private String subject;
- /**郵件內容**/
- private String content;
- /**附件**/
- private MultipartFile[] attachment =new MultipartFile[0];
- //////////////////////////解析郵件地址////////////////////////////// public String[] getAddress() {
- if(!StringUtil.hasLength(this.addressee)) {
- return null;
- }
- addressee = addressee.trim();
- addressee.replaceAll(",;",
";");
- addressee.replaceAll(" ",
";");
- addressee.replaceAll(",",
";");
- addressee.replaceAll(",,",
";");
- addressee.replaceAll("|",
";");
- return addressee.split(";"); }
- /////////////////////////////Getter && Setter///////////////////////////////
- ...... }
- package com.zhangjihao.bean;
- import java.io.Serializable;
- import org.springframework.web.multipart.MultipartFile;
- import com.zhangjihao.util.StringUtil;
- /**
- * 說明:<br>
- *
- * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
- public class Email implements Serializable {
- private static final long serialVersionUID = 9063903350324510652L;
-
- /**用戶組:可以按用戶組來批量發(fā)送郵件**/
- private UserGroups userGroups;
- /**收件人**/
- private String addressee;
- /**抄送給**/
- private String cc;
- /**郵件主題**/
- private String subject;
- /**郵件內容**/
- private String content;
- /**附件**/
- private MultipartFile[] attachment = new MultipartFile[0];
-
- //////////////////////////解析郵件地址////////////////////////////// public String[] getAddress() {
- if(!StringUtil.hasLength(this.addressee)) {
- return null;
- }
- addressee = addressee.trim();
- addressee.replaceAll(";", ";");
- addressee.replaceAll(" ", ";");
- addressee.replaceAll(",", ";");
- addressee.replaceAll(",,", ";");
- addressee.replaceAll("|", ";");
- return addressee.split(";"); }
- /////////////////////////////Getter && Setter///////////////////////////////
- ...... }
這個類就是一個簡單的JavaBean,,用于封裝郵件數(shù)據(jù),,對于習慣使用Struts框架的讀者,完全可以把它理解為一個ActionForm,。但對于MultipartFile類型且是數(shù)組的attachment屬性可能較難理解,,熟悉Struts框架的可以看作是FormFile,在Struts2中可能好理解些,。筆者使用的是Spring MVC,,框架中內置了這種屬性編輯器,因此很容易地將form表單上傳的文件進行轉換成這個字段,。
我們來看看WEB層調用,,其實到此為止,就已經完成本文的主題了,,因此WEB怎么調用都是圍繞MailService中的三個方法,,為便有全面的認識,將代碼列出,,不過最好需要了解Spring @MVC的一些知識,。
MailController.java:
- package com.zhangjihao.web.controller.system;
- import java.util.List;
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.mail.javamail.JavaMailSender;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.ModelMap;
- import org.springframework.validation.BindingResult;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import com.zhangjihao.bean.Email;
- import com.zhangjihao.domain.user.User;
- import com.zhangjihao.service.MailService;
- import com.zhangjihao.service.UserService;
- import com.zhangjihao.util.StringUtil;
- import com.zhangjihao.web.controller.MasterController;
- import com.zhangjihao.web.validator.EmailValidator;
- /**
- * 說明:<br>
- * 郵件發(fā)送處理器
- * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
- @Controllerpublic class MailControllerextends MasterController {
- @Resource MailService mailService;
- @Resource UserService userService;
- @RequestMapping(value =
"/sendEmail", method=RequestMethod.GET)
public String sendEmail(@RequestParam(value="email",required=false) String singleEmailAddress
, HttpServletRequest request){
- Email email = new Email();
- if(StringUtil.hasLength(singleEmailAddress)){
- email.setAddressee(singleEmailAddress);
- }
- request.setAttribute("email", email);
- return "system/sendMail"; }@RequestMapping(value =
"/sendEmail", method=RequestMethod.POST)
- public String send(
- @ModelAttribute Email email,//Spring MVC將form表單的數(shù)據(jù)封裝到這個對象中
- BindingResult result, ModelMap model, HttpServletRequest request){
- try {
- new EmailValidator().validate(email, result);
- if(result.hasErrors()){
- throw new RuntimeException("數(shù)據(jù)填寫不正確");
- }
- if(email.getEmailGroup()!=null){
- List<User> users = userService.getUserByUserGroups(email.getEmailGroup(),"userName,email",
null,null); StringBuffer sb =
new StringBuffer(StringUtil.hasLengthBytrim(email.getAddressee()) ? (email.getAddressee().trim() +";") :
"");
- for(User user : users){
- sb.append(user.getEmail()).append(";");
- } email.setAddressee(sb.toString());
- }
- if(email.getAddress()==null || email.getAddress().length==0){ request.setAttribute("message","沒有收件人!");
return"message"; }
- mailService.sendMail(email); //大于5個收件人時,分流器會自動選擇異步方式發(fā)送
- request.setAttribute("message", mailService.getMessage().append("本次共發(fā)送了 ").append(email.getAddress().length).append(" 封郵件.").toString());
- }
- catch (Exception e) {
- request.setAttribute("message","Has errors! The info by "+e.getMessage()+"<br/>Can log in to view more detailed information on abnormalities.");
- log.error(this.getClass().getName()+"中發(fā)生異常---------------:\n", e);
- }
- return BACK + "message";
- }
- }
- package com.zhangjihao.web.controller.system;
- import java.util.List;
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.mail.javamail.JavaMailSender;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.ModelMap;
- import org.springframework.validation.BindingResult;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import com.zhangjihao.bean.Email;
- import com.zhangjihao.domain.user.User;
- import com.zhangjihao.service.MailService;
- import com.zhangjihao.service.UserService;
- import com.zhangjihao.util.StringUtil;
- import com.zhangjihao.web.controller.MasterController;
- import com.zhangjihao.web.validator.EmailValidator;
- /**
- * 說明:<br>
- * 郵件發(fā)送處理器
- * @author 張紀豪
- * @version
- * Build Time Jul 24, 2009
- */
- @Controllerpublic class MailController extends MasterController {
- @Resource MailService mailService;
- @Resource UserService userService;
- @RequestMapping(value = "/sendEmail", method=RequestMethod.GET) public String sendEmail(@RequestParam(value="email",required=false) String singleEmailAddress , HttpServletRequest request){
- Email email = new Email();
- if(StringUtil.hasLength(singleEmailAddress)){
- email.setAddressee(singleEmailAddress);
- }
- request.setAttribute("email", email);
- return "system/sendMail"; } @RequestMapping(value = "/sendEmail", method=RequestMethod.POST)
- public String send(
- @ModelAttribute Email email, //Spring MVC將form表單的數(shù)據(jù)封裝到這個對象中
- BindingResult result, ModelMap model, HttpServletRequest request){
- try {
- new EmailValidator().validate(email, result);
- if(result.hasErrors()){
- throw new RuntimeException("數(shù)據(jù)填寫不正確");
- }
- if(email.getEmailGroup()!=null){
- List<User> users = userService.getUserByUserGroups(email.getEmailGroup(), "userName,email", null, null); StringBuffer sb = new StringBuffer(StringUtil.hasLengthBytrim(email.getAddressee()) ? (email.getAddressee().trim() + ";") : "");
- for(User user : users){
- sb.append(user.getEmail()).append(";");
- } email.setAddressee(sb.toString());
- }
- if(email.getAddress()==null || email.getAddress().length==0){ request.setAttribute("message", "沒有收件人!"); return "message"; }
- mailService.sendMail(email); //大于5個收件人時,,分流器會自動選擇異步方式發(fā)送
- request.setAttribute("message", mailService.getMessage().append("本次共發(fā)送了 ").append(email.getAddress().length).append(" 封郵件.").toString());
- }
- catch (Exception e) {
- request.setAttribute("message", "Has errors! The info by "+e.getMessage()+"<br/>Can log in to view more detailed information on abnormalities.");
- log.error(this.getClass().getName()+"中發(fā)生異常---------------:\n", e);
- }
- return BACK + "message";
- }
- }
當一個get方法請求的連接進來,,此控制器會轉向一個html頁面,其頁面中有form表單,,表單中的字段與Email.java對應,,當post方法過來后,Spring MVC會把表單中的數(shù)據(jù)填充到Email對象中,,交給MailService處理就ok了,。
最后講述下最容易出現(xiàn)的錯誤:
網上很多人都說J2EE5兼容性不好,例如典型的javamail1.4中包與J2EE5中包接口包引起沖突,,導致單元測試經常報如下錯誤:
java.lang.NoClassDefFoundError: com/sun/mail/util/BEncoderStream
當然這個錯誤是沒有將javamail的實現(xiàn)者引進工程(沒有導包),但導包后,,就會出現(xiàn)另外一個錯誤:
java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream
此時甚至web容器都無法啟動,,經常會有網友們?yōu)檫@兩個異常搞得焦頭爛額,如此更換J2EE1.4,,會對工程造成影響,。但是一定要把概念弄清楚,問題就好解決,。J2EE5中mail.jar包定義的只是接口,,沒有實現(xiàn),是不能真正發(fā)送郵件的,,但開發(fā)編譯肯定是可以過去的,,因為我們是針對J2EE規(guī)范編的程序。而運行期用Sun公司的JavaMail1.4的實現(xiàn)才可以開始發(fā)送郵件,但老大為什么把這兩個弄沖突了?
筆者的解決辦法是:
開發(fā)期不要導包,,運行期將javamail1.4壓縮文件中的mail.jar包放入到tomcat\lib目錄下,,這樣完全可以通過開發(fā)和運行。若要做單元測試則新開一個Java Project,,注意,,不是web工程,此時可以將javamail1.4壓縮包中的mail.jar放入到工程的classpath下,。
|