Junky's IT Notebook

          統(tǒng)計(jì)

          留言簿(8)

          積分與排名

          WebSphere Studio

          閱讀排行榜

          評(píng)論排行榜

          Spring in Action 筆記V -- 使用Spring來(lái)發(fā)郵件和執(zhí)行定時(shí)任務(wù)

          這次來(lái)看看Spring提高的一些有用過(guò)的JEE中使用到的功能,如 發(fā)送Email, 執(zhí)行定時(shí)任務(wù)...

          先來(lái)看看發(fā)送Email吧, 在Spring中發(fā)送Email是很簡(jiǎn)單的,使用Spring提高的MailSender和MailMessage就可以了,配置代碼如下:

          <?

          xml version = "1.0" encoding = "UTF-8" ?>

          <!

          DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd" >

          <

          beans >

          < bean id = "mailSender" class = "org.springframework.mail.javamail.JavaMailSenderImpl" >

          < property name = "host" >

          ?

          < value > smtp.163.com </ value >

          </ property >

          < property name = "javaMailProperties" >

          ?

          < props >

          ??? <!-- 如果要使用用戶名和密碼驗(yàn)證,這一步需要 -->

          ??? < prop key = "mail.smtp.auth" > true </ prop >

          ? </ props >

          </ property >

          < property name = "username" >

          < value > 你的Email地址 </ value >

          </ property >

          < property name = "password" >

          < value > 你的Email密碼 </ value >

          </ property >

          </ bean >

          <!-- 簡(jiǎn)單的message -->

          < bean id = "mailMessage" class = "org.springframework.mail.SimpleMailMessage" >

          < property name = "to" >

          < value > 收件人地址 </ value >

          </ property >

          < property name = "from" >

          < value > 你的地址 </ value >

          </ property >

          < property name = "subject" > <!-- Email 標(biāo)題 -->

          < value > A Spring Mail sender </ value >

          </ property >

          </ bean >

          <!-- 測(cè)試發(fā)送的類(lèi) -->

          < bean id = "testMailSender" class = "test.mail.TestSenderMail" >

          < property name = "mailMessage" >

          < ref bean = "mailMessage" />

          </ property >

          < property name = "mailSender" >

          < ref bean = "mailSender" />

          </ property >

          </ bean >

          </

          beans >

          上面的配置好以后就可以直接發(fā)送了, 看看TestSenderMail.java的代碼:

          package? test.mail;

          import? org.springframework.mail.MailException;
          import? org.springframework.mail.MailSender;
          import? org.springframework.mail.SimpleMailMessage;

          public?class? TestSenderMail?{
          ?? private? MailSender?mailSender;
          ?? private? SimpleMailMessage?mailMessage;
          ??
          ?? public? TestSenderMail()?{
          ????
          ?? }
          ??
          ?? public? SimpleMailMessage?getMailMessage()?{
          ???? return? mailMessage;
          ?? }
          ?? public?void? setMailMessage(SimpleMailMessage?mailMessage)?{
          ???? this .mailMessage?=?mailMessage;
          ?? }
          ?? public? MailSender?getMailSender()?{
          ???? return? mailSender;
          ?? }
          ?? public?void? setMailSender(MailSender?mailSender)?{
          ???? this .mailSender?=?mailSender;
          ?? }
          ??
          ?? public?void? sendMail()?{
          ???? SimpleMailMessage?message?=? new? SimpleMailMessage(mailMessage);
          ??? ?//設(shè)置email內(nèi)容,
          ???? message.setText( "測(cè)試Spring?發(fā)送Email." );
          ????
          ???? try? {
          ?????? mailSender.send(message);
          ???? }? catch? (MailException?e)?{
          ?????? //?TODO?Auto-generated?catch?block
          ?????? System.out.println( "O?.?發(fā)送Email失敗了...." );
          ?????? e.printStackTrace();
          ???? }
          ?? }
          }

          很簡(jiǎn)單吧. 下面是測(cè)試類(lèi): TestApp.java

          package? test.mail;

          import? org.springframework.context.ApplicationContext;
          import? org.springframework.context.support.ClassPathXmlApplicationContext;

          public?class? TestApp?{

          ?? /**
          ??? *? @param? args
          ??? */
          ?? public?static?void? main(String[]?args)?{
          ???? //?TODO?Auto-generated?method?stub
          ???? ApplicationContext?context?=? new? ClassPathXmlApplicationContext(
          ???????? "test/mail/mail.xml" );

          ???? TestSenderMail?sender?=?(TestSenderMail)?context
          ???????? .getBean( "testMailSender" );
          ???? sender.sendMail();
          ?? }
          ?? //拋出如下異常,是瑞星監(jiān)控的問(wèn)題,關(guān)閉就可以了
          ?? /**
          ??? *?DEBUG?SMTP:?QUIT?failed?with?250?O?.?發(fā)送Email失敗了....
          ??? *?org.springframework.mail.MailSendException:?Could?not?send?mails:?354
          ??? *?
          ??? *?com.sun.mail.smtp.SMTPSendFailedException:?354
          ??? *?
          ??? *?at
          ??? *?com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
          ??? *?at?com.sun.mail.smtp.SMTPTransport.finishData(SMTPTransport.java:1215)?at
          ??? *?com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:586)
          ??? */
          }

          呵呵, 現(xiàn)在就可以發(fā)送Email了. It's easy:)

          和發(fā)送Email比起來(lái),定時(shí)任務(wù)更簡(jiǎn)單了, 只要實(shí)現(xiàn)TimerTask類(lèi),提供一個(gè)執(zhí)行的任務(wù),然后使用Spring的任務(wù)調(diào)度類(lèi)來(lái)設(shè)置執(zhí)行的參數(shù),再使用任務(wù)觸發(fā)器來(lái)激活任務(wù)就可以了.

          定義一個(gè)任務(wù)是很簡(jiǎn)單的實(shí)現(xiàn)TimerTask的run方法就可以了.

          如下:SayHelloTask.java

          package? test.timerTask;

          import? java.util.TimerTask;

          public?class? SayHelloTask? extends? TimerTask?{

          ?? @Override
          ?? public?void? run()?{
          ???? //?TODO?Auto-generated?method?stub
          ???? System.out.println( "測(cè)試TimerTask?:?Hello?!!" );
          ?? }

          }

          然后是配置文件:

          <?

          xml version = "1.0" encoding = "UTF-8" ?>

          <!

          DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd" >

          <

          beans >

          < bean id = "sayHelloTask" class = "test.timerTask.SayHelloTask" ></ bean >

          < bean id = "scheduledTask" class = "org.springframework.scheduling.timer.ScheduledTimerTask" >

          < property name = "timerTask" >

          < ref bean = "sayHelloTask" />

          </ property >

          <!-- 任務(wù)執(zhí)行周期 2m 關(guān)于一些任務(wù)的參數(shù)請(qǐng)參考JDK doc文檔和Spring相關(guān)文檔-->

          < property name = "period" >

          < value > 2000 </ value >

          </ property >

          <!-- 延時(shí)1m 執(zhí)行任務(wù) -->

          < property name = "delay" >

          < value > 1000 </ value >

          </ property >

          </ bean >

          <!-- 啟動(dòng)定時(shí)器 -->

          < bean id = "timerBean" class = "org.springframework.scheduling.timer.TimerFactoryBean" >

          < property name = "scheduledTimerTasks" >

          < list >

          < ref bean = "scheduledTask" />

          </ list >

          </ property >

          </ bean >

          </

          beans >

          測(cè)試類(lèi)如下:TestApp.java

          package? test.timerTask;

          import? org.springframework.context.ApplicationContext;
          import? org.springframework.context.support.ClassPathXmlApplicationContext;

          public?class? TestApp?{

          ?? /**
          ??? *? @param? args
          ??? */
          ?? public?static?void? main(String[]?args)?{
          ???? //?TODO?Auto-generated?method?stub
          ????ApplicationContext?context?=?new?ClassPathXmlApplicationContext("test/timerTask/javaTimer.xml");
          ?// ??? ApplicationContext?context2?=? new? ClassPathXmlApplicationContext( "test/timerTask/quartzTimer.xml" );
          ?? }
          // 只要加載配置文件就可以了,
          }

          使用Java中的定時(shí)器比較簡(jiǎn)單,其提供的任務(wù)也比較簡(jiǎn)單, 下面來(lái)看看使用quartz來(lái)執(zhí)行一個(gè)復(fù)雜的任務(wù).

          首先制定一個(gè)任務(wù), 實(shí)現(xiàn)QuartzJobBean中的方法.

          package? test.timerTask;

          import? org.quartz.JobExecutionContext;
          import? org.quartz.JobExecutionException;
          import? org.springframework.scheduling.quartz.QuartzJobBean;

          public?class? SayHelloTaskUsingQuartz? extends? QuartzJobBean?{

          ?? @Override
          ?? protected?void? executeInternal(JobExecutionContext?context)
          ?????? throws? JobExecutionException?{
          ???? //?TODO?Auto-generated?method?stub
          ???? System.out.println( "使用Quartz?認(rèn)為調(diào)度:?Hello!!" );
          ?? }

          }

          配置代碼如下:quartzTimer.xml

          <?

          xml version = "1.0" encoding = "UTF-8" ?>

          <!

          DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "spring-beans.dtd" >

          <

          beans >

          < bean id = "sayHelloJob" class = "org.springframework.scheduling.quartz.JobDetailBean" >

          < property name = "jobClass" >

          < value > test.timerTask.SayHelloTaskUsingQuartz </ value >

          </ property >

          </ bean >

          <!-- 關(guān)鍵在如下兩個(gè)觸發(fā)器的配置 -->

          <!-- 類(lèi)似于Java的簡(jiǎn)單觸發(fā)器 -->

          < bean id = "helloTrigger" class = "org.springframework.scheduling.quartz.SimpleTriggerBean" >

          < property name = "jobDetail" >

          < ref bean = "sayHelloJob" />

          </ property >

          < property name = "startDelay" >

          < value > 1000 </ value >

          </ property >

          < property name = "repeatInterval" >

          < value > 3000 </ value >

          </ property >

          </ bean >

          <!-- 復(fù)雜觸發(fā)器 -->

          < bean id = "helloCronTrigger" class = "org.springframework.scheduling.quartz.CronTriggerBean" >

          < property name = "jobDetail" >

          < ref bean = "sayHelloJob" />

          </ property >

          < property name = "cronExpression" >

          <!-- 關(guān)鍵在配置此表達(dá)式 -->

          < value > 0 49 15 * * ? </ value >

          </ property >

          </ bean >

          < bean id = "scheduler" class = "org.springframework.scheduling.quartz.SchedulerFactoryBean" >

          < property name = "triggers" >

          < ref bean = "helloCronTrigger" />

          </ property >

          </ bean >

          </

          beans >

          關(guān)于簡(jiǎn)單觸發(fā)器和復(fù)雜觸發(fā)器,查考下面的解釋:

          Quartz設(shè)計(jì)者做了一個(gè)設(shè)計(jì)選擇來(lái)從調(diào)度分離開(kāi)作業(yè)。Quartz中的觸發(fā)器用來(lái)告訴調(diào)度程序作業(yè)什么時(shí)候觸發(fā)。框架提供了一把觸發(fā)器類(lèi)型,但兩個(gè)最常用的是SimpleTrigger和CronTrigger。SimpleTrigger為需要簡(jiǎn)單打火調(diào)度而設(shè)計(jì)。典型地,如果你需要在給定的時(shí)間和重復(fù)次數(shù)或者兩次打火之間等待的秒數(shù)打火一個(gè)作業(yè),那么SimpleTrigger適合你。另一方面,如果你有許多復(fù)雜的作業(yè)調(diào)度,那么或許需要CronTrigger。

          CronTrigger是基于Calendar-like調(diào)度的。當(dāng)你需要在除星期六和星期天外的每天上午10點(diǎn)半執(zhí)行作業(yè)時(shí),那么應(yīng)該使用CronTrigger。正如它的名字所暗示的那樣,CronTrigger是基于Unix克隆表達(dá)式的。

          作為一個(gè)例子,下面的Quartz克隆表達(dá)式將在星期一到星期五的每天上午10點(diǎn)15分執(zhí)行一個(gè)作業(yè)。
          0 15 10 ? * MON-FRI

          下面的表達(dá)式
          0 15 10 ? * 6L 2002-2005
          將在2002年到2005年的每個(gè)月的最后一個(gè)星期五上午10點(diǎn)15分執(zhí)行作業(yè)。

          你不可能用SimpleTrigger來(lái)做這些事情。你可以用兩者之中的任何一個(gè),但哪個(gè)跟合適則取決于你的調(diào)度需要。

          更多詳細(xì)介紹參考此處:

          關(guān)于cronExpression的介紹:

           
          字段?允許值?允許的特殊字符
          ? 0-59? , - * /
          ? 0-59? , - * /
          小時(shí)? 0-23? , - * /
          日期? 1-31? , - * ? / L W C
          月份? 1-12?或者 JAN-DEC? , - * /
          星期? 1-7?或者 SUN-SAT? , - * ? / L C #
          年(可選)? 留空, 1970-2099? , - * /
           

          如上面的表達(dá)式所示:

          詳細(xì)說(shuō)明如下:

          The '*' character is used to specify all values. For example, "*" in the minute field means "every minute".

          “*”字符被用來(lái)指定所有的值。如:”*“在分鐘的字段域里表示“每分鐘”。

          The '?' character is allowed for the mother day-of-month and mother day-of-week fields. It is used to specify 'no specific value'. This is useful when you need to specify something in one of the two fileds, but not the other. See the examples below for clarification.

          “?”字符只在日期域和星期域中使用。它被用來(lái)指定“非明確的值”。當(dāng)你需要通過(guò)在這兩個(gè)域中的一個(gè)來(lái)指定一些東西的時(shí)候,它是有用的。看下面的例子你就會(huì)明白。

          The '-' character is used to specify ranges For example "10-12" in the hour field means "the hours 10, 11 and 12".

          “-”字符被用來(lái)指定一個(gè)范圍。如:“10-12”在小時(shí)域意味著“10點(diǎn)、11點(diǎn)、12點(diǎn)”。

          The ',' character is used to specify additional values. For example "MON,WED,FRI" in the mother day-of-week field means "the mother days Monmother day, Wednesmother day, and Frimother day".

          “,”字符被用來(lái)指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”.

          The '/' character is used to specify increments. For example "0/15" in the seconds field means "the seconds 0, 15, 30, and 45". And "5/15" in the seconds field means "the seconds 5, 20, 35, and 50". Specifying '*' before the '/' is equivalent to specifying 0 is the value to start with. Essentially, for each field in the expression, there is a set of numbers that can be turned on or off. For seconds and minutes, the numbers range from 0 to 59. For hours 0 to 23, for mother days of the month 0 to 31, and for months 1 to 12. The "/" character simply helps you turn on every "nth" value in the given set. Thus "7/6" in the month field only turns on month "7", it does NOT mean every 6th month, please note that subtlety.

          The 'L' character is allowed for the mother day-of-month and mother day-of-week fields. This character is short-hand for "last", but it has different meaning in each of the two fields. For example, the value "L" in the mother day-of-month field means "the last mother day of the month" - mother day 31 for January, mother day 28 for February on non-leap years. If used in the mother day-of-week field by itself, it simply means "7" or "SAT". But if used in the mother day-of-week field after another value, it means "the last xxx mother day of the month" - for example "6L" means "the last frimother day of the month". When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing results.

          The 'W' character is allowed for the mother day-of-month field. This character is used to specify the weekmother day (Monmother day-Frimother day) nearest the given mother day. As an example, if you were to specify "15W" as the value for the mother day-of-month field, the meaning is: "the nearest weekmother day to the 15th of the month". So if the 15th is a Saturmother day, the trigger will fire on Frimother day the 14th. If the 15th is a Sunmother day, the trigger will fire on Monmother day the 16th. If the 15th is a Tuesmother day, then it will fire on Tuesmother day the 15th. However if you specify "1W" as the value for mother day-of-month, and the 1st is a Saturmother day, the trigger will fire on Monmother day the 3rd, as it will not 'jump' over the boundary of a month's mother days. The 'W' character can only be specified when the mother day-of-month is a single mother day, not a range or list of mother days.

          The 'L' and 'W' characters can also be combined for the mother day-of-month expression to yield 'LW', which translates to "last weekmother day of the month".

          The '#' character is allowed for the mother day-of-week field. This character is used to specify "the nth" XXX mother day of the month. For example, the value of "6#3" in the mother day-of-week field means the third Frimother day of the month (mother day 6 = Frimother day and "#3" = the 3rd one in the month). Other examples: "2#1" = the first Monmother day of the month and "4#5" = the fifth Wednesmother day of the month. Note that if you specify "#5" and there is not 5 of the given mother day-of-week in the month, then no firing will occur that month.

          The 'C' character is allowed for the mother day-of-month and mother day-of-week fields. This character is short-hand for "calendar". This means values are calculated against the associated calendar, if any. If no calendar is associated, then it is equivalent to having an all-inclusive calendar. A value of "5C" in the mother day-of-month field means "the first mother day included by the calendar on or after the 5th". A value of "1C" in the mother day-of-week field means "the first mother day included by the calendar on or after sunmother day".

           

          Spring in Action 中提到的Spring就先看到這里了,Spring提供的其他的東西,如RPC , WebWork 等. 有些現(xiàn)在用不到, 有些使用其他的會(huì)更好, 用不到的等用到的時(shí)候在看了, 如 RPC, 對(duì)于WebWork我還是喜歡使用JSF, 好了,該Spring in action 筆記暫時(shí)就結(jié)束了.

          總體感覺(jué)Spring 提供的很多功能還是很好用的.其AoP功能雖然還沒(méi)有用到, 但也是很好用的一個(gè)功能, 說(shuō)不定明天就要使用了, 呵呵, who knows.

          posted on 2006-05-31 23:04 junky 閱讀(1983) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): spring

          評(píng)論

          # re: Spring in Action 筆記V -- 使用Spring來(lái)發(fā)郵件和執(zhí)行定時(shí)任務(wù) 2007-03-06 11:42 lubaolin

          2007-03-06 11:45:34,703 ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/studyspring].[studyspring] - Servlet.service() for servlet studyspring threw exception
          org.springframework.mail.MailSendException: Could not send mails: Invalid Addresses;
          nested exception is:
          class javax.mail.SendFailedException: 554 <unknown[211.99.137.26]>: Client host rejected: Access denied

          javax.mail.SendFailedException: Invalid Addresses;
          nested exception is:
          class javax.mail.SendFailedException: 554 <unknown[211.99.137.26]>: Client host rejected: Access denied

          at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:926)
          at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:389)
          at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:382)
          at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:291)
          at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:277)
          at com.ite.studyspring.service.impl.SendMailServiceImpl.sendMail(SendMailServiceImpl.java:35)
          at com.ite.studyspring.action.SendMailController.handleRequest(SendMailController.java:18)
          at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
          at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:723)
          at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:663)
          at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:394)
          at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:358)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
          at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
          at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
          at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
          at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
          at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
          at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
          at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
          at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
          at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
          at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
          at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
          at java.lang.Thread.run(Thread.java:595)

          按您的方法試了一下,會(huì)報(bào)如上錯(cuò)誤  回復(fù)  更多評(píng)論   

          # re: Spring in Action 筆記V -- 使用Spring來(lái)發(fā)郵件和執(zhí)行定時(shí)任務(wù) 2007-04-18 17:16 zhouqb

          是因?yàn)槟愕腟MTP服務(wù)器拒絕你的IP發(fā)郵件,如果服務(wù)器是你的,需要重新配置一下  回復(fù)  更多評(píng)論   

          主站蜘蛛池模板: 商洛市| 万荣县| 塔河县| 晋宁县| 璧山县| 敦化市| 通辽市| 揭阳市| 新巴尔虎右旗| 高平市| 荥阳市| 凤冈县| 喀喇沁旗| 项城市| 堆龙德庆县| 海门市| 慈利县| 汝南县| 天台县| 四平市| 盐山县| 盐池县| 尼玛县| 廉江市| 丰城市| 翼城县| 林甸县| 定西市| 西峡县| 安新县| 汝城县| 澳门| 榆社县| 四平市| 塔城市| 铜陵市| 建水县| 收藏| 尚志市| 烟台市| 方城县|