昨天 老大 交下一件任務,在Spring框架下構建一個郵件自動發送模塊,接到此任務的第一個想法是利用Timer, 它小巧功能夠用.
以下是寫的一個測試類.写道
package umt.michael.tsk.test;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* @Title: Test.java
* @Package umt.michael.tsk.test
* @Description: TODO
* @author MichaelYang
* @Email apac.yang@gmail.com
* @date 2011/10/13 下午9:19:01
* @version V1.0
*/
class DateTask extends TimerTask{
@Override
public void run() {
System.out.println("現在時間:" + new Date());
}
}
public class Test {
/**
* @Title: main
* @Description: TODO
* @param args
* @return void
*/
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new DateTask(), 1000,5000);
try{
Thread.sleep(20000);
}catch(Exception e){
System.err.println(e.getMessage());
e.printStackTrace();
}
System.out.println("結束時間是:" + new Date());
timer.cancel();
}
}
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* @Title: Test.java
* @Package umt.michael.tsk.test
* @Description: TODO
* @author MichaelYang
* @Email apac.yang@gmail.com
* @date 2011/10/13 下午9:19:01
* @version V1.0
*/
class DateTask extends TimerTask{
@Override
public void run() {
System.out.println("現在時間:" + new Date());
}
}
public class Test {
/**
* @Title: main
* @Description: TODO
* @param args
* @return void
*/
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new DateTask(), 1000,5000);
try{
Thread.sleep(20000);
}catch(Exception e){
System.err.println(e.getMessage());
e.printStackTrace();
}
System.out.println("結束時間是:" + new Date());
timer.cancel();
}
}
結果為:
現在時間:Thu Oct 13 21:30:12 CST 2011
現在時間:Thu Oct 13 21:30:17 CST 2011
現在時間:Thu Oct 13 21:30:22 CST 2011
現在時間:Thu Oct 13 21:30:27 CST 2011
結束時間是:Thu Oct 13 21:30:31 CST 2011
頭兒卻明確要用Quartz 這個任務調度框架.沒辦法,只好拼了,从Quartz官网 http://www.quartz-scheduler.org/ 上下载jar包 现在该版本已经到了2.10,但是在国外一个网站发现貌似 2.1 和Spring3.x 无法兼容,没有验证,为了安全起见,我下载的是穩定版本quartz1.8.5. 相關配置如下.
Web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/spring-quartz.xml</param-value> </context-param> <!-- 配置日誌文件打印 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/properties/log4j.properties</param-value> </context-param> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>6000</param-value> </context-param> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <!-- 此監聽器 用於加載組件 --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 字符流過濾器 --> <filter> <filter-name>characterEncoding</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置代理轉發請求 --> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.saq.michael.servlet.HttpServletProxy</servlet-class> <init-param> <param-name>targetServlet</param-name> <param-value>loginServlet</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> </web-app>
spring-quartz.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<import resource="db-config.xml" />
<!-- 定時執行的任務 -->
<bean id="jobDetailBean" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.saq.michael.job.SendEmailJob"/>
<property name="jobDataAsMap">
<map>
<entry key="sendEmailService" value-ref="sendEmailService"/>
</map>
</property>
</bean>
<!--觸發器 -->
<bean id="simpleTriggerBean" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<ref bean="jobDetailBean"/>
</property>
<property name="repeatInterval">
<value>45000</value>
</property>
<property name="startDelay">
<value>1000</value>
</property>
</bean>
<!-- 任務調度器, 可配置 dataSoure -->
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTriggerBean"/>
</list>
</property>
</bean>
</beans>
db-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--加載屬性文件
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/properties/common.properties</value>
</list>
</property>
</bean>
-->
<bean id="loginServlet" class="com.saq.michael.servlet.CommonServlet">
<property name="operation" ref="operation" />
</bean>
<bean id="sendEmailService" class="com.saq.michael.service.impl.SendEmailService">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://XXXXXXX:1433;DatabaseName=testPaper" />
<property name="username" value="XXX" />
<property name="password" value="XXXXX" />
</bean>
<!-- set TransactionManager message-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--利用了拦截器的原理-->
<bean id="transactionInterceptor" lazy-init="true" scope="singleton"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager">
</property>
<!-- 配置事务属性
-Exception 表示有Exception抛出时,事务回滚. readonly 就是read only, 一般用于查询的方法,优化作用.
prop key="delete*" 表示方法名 可以用戶通配符*
PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
-->
<property name="transactionAttributes">
<props>
<prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="operate*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="sendMail">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="find*">PROPAGATION_NEVER,readOnly</prop>
<prop key="get*">PROPAGATION_NEVER,readOnly</prop>
</props>
</property>
</bean>
<!--Spring 自動代理所有的 ServiceName 為 *ServiceImpl 的Service-->
<bean id="txProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
</beans>
SendEmailService.java
package com.saq.michael.service.impl;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import com.saq.michael.bean.EmailAddress;
import com.saq.michael.method.reportViaUrl;
/**
* @Title: SendEmailService.java
* @Package com.saq.michael.service.impl
* @Description: 郵件發送,數據更新.
* @author MichaelYang
* @Email michael.yang@earlylight.com.hk
* @date Oct 20, 2011 2:48:34 PM
* @version V1.0
*/
public class SendEmailService {
private JdbcTemplate jdbcTemplate;
private Connection con ;
private static final Log logger = LogFactory.getLog(SendEmailService.class);
public void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null)
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
/**
* 發送郵件的相關信息
* @param mailSender
* @return
* @throws SQLException
* @throws Exception
* @throws IOException
* @throws ServletException
*/
public boolean sendMail(EmailAddress emailAddress,File file) throws MessagingException, SQLException{
logger.info(" ... 開始發送郵件.... ");
if(con == null || con.isClosed()) {
con = this.getConnection();
logger.info(con.hashCode());
}
String msg = reportViaUrl.reportHTMLStringViaURL(emailAddress.getUrl(),con); //獲取郵件內容
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("XXXXX");
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
message.setContent(msg, "text/html;charset=UTF-8");//文本類型
message.setSubject(msg, "UTF-8");
helper.setTo(emailAddress.getRecipients());
helper.setText(msg);
if(file!=null && file.length()>0){
helper.addAttachment(file.getName(), file);//添加附件
}
mailSender.send(message);
logger.info(" ....... ");
return true;
}
/**
* 獲取異常信息.
* @param throwable
* @return String exceptionMsg
*/
public String getException(Throwable throwable){
StringBuffer resultMess =new StringBuffer();
if(resultMess.length()>500){
return resultMess.substring(0, 500);
}else{
resultMess.append(throwable.toString()+"\n");
if(throwable.getCause()!=null){
resultMess.append("Cause By: ");
resultMess.append(getException(throwable.getCause()));
}
}
return resultMess.length()>500?resultMess.substring(0, 500):resultMess.toString();
}
/**
* 從數據庫中讀取相應的數據,并執行相應操作
* @param <EmaillAddress>
* @param con
* @return
* @throws SQLException
* @throws IOException
*/
@SuppressWarnings({"unused","unchecked"})
public List<EmailAddress> getEmailAddress(String sql){
System.out.println(" ... 查詢出郵件地址以及對應的URL ... ");
System.out.println(" ... SQL:"+sql+"... ");
List<EmailAddress> list = this.jdbcTemplate.query(sql, new EmailAddressRowMapper());
return list;
}
/**
* 更新發送成功的數據
* @param list
* @return
*/
@SuppressWarnings("unchecked")
public boolean updateEmailSuccess(final List<Integer> list){
this.jdbcTemplate.update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement ps = con.prepareStatement("UPDATE EMAIL_ADDRESS_URL SET ENABLE=0 WHERE PK_EAU_ID = ?");
for(int pk_id:list){
System.out.println(" PK_ID: "+pk_id);
ps.setInt(1, pk_id);
ps.addBatch();
}
return ps;
}
});
return true;
}
/**
*
* @param list
* @return
*/
@SuppressWarnings("unchecked")
public boolean updateEmailSuccess(final int pk_id){
this.jdbcTemplate.update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement ps = con.prepareStatement("UPDATE EMAIL_ADDRESS_URL SET ENABLE=0 WHERE PK_EAU_ID = ?");
System.out.println(" PK_ID: "+pk_id);
ps.setInt(1, pk_id);
return ps;
}
});
return true;
}
public boolean updateEmailFailed(final EmailAddress address){
final String SQL = "UPDATE EMAIL_ADDRESS_URL SET modifiedDate = ?),SET tryAgain =1 WHERE PK_EAU_ID = ?";
logger.info(SQL);
this.jdbcTemplate.update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con) throws SQLException{
PreparedStatement ps = con.prepareStatement(SQL);
//System.out.println(" PK_ID: "+address.getId());
ps.setDate(1, (java.sql.Date) new Date());
ps.setInt(2, address.getId());
return ps;
}
});
return true;
}
public boolean updateEmailFailed(final List<EmailAddress> list){
final String SQL = "UPDATE EMAIL_ADDRESS_URL SET modifiedDate = getDate(),SET tryAgain =1,SET exceptionMsg =? WHERE PK_EAU_ID = ?";
logger.info(SQL);
this.jdbcTemplate.update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con) throws SQLException{
PreparedStatement ps = con.prepareStatement(SQL);
for(EmailAddress address:list){
System.out.println(" PK_ID: "+address.getId());
ps.setString(1, address.getExceptionMsg());
ps.setInt(2, address.getId());
ps.addBatch();
}
return ps;
}
});
return true;
}
public Connection getConnection() throws CannotGetJdbcConnectionException, SQLException{
if(con == null || con.isClosed()){
con = DataSourceUtils.getConnection(this.jdbcTemplate.getDataSource());
logger.info(" [創建Connection hashCode:"+con.hashCode()+" ]");
}
return con;
}
}
SendEmailJob.java
package com.saq.michael.job;
import java.sql.SQLException;
import java.util.List;
import javax.mail.MessagingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.saq.michael.bean.EmailAddress;
import com.saq.michael.service.impl.SendEmailService;
/**
* @Title: TestJob.java
* @Package com.saq.michael.job
* @Description: 郵件發送.
* @author MichaelYang
* @Email michael.yang@earlylight.com.hk
* @date Oct 13, 2011 8:41:30 PM
* @version V1.0
* @param <EmaillAddress>
*/
public class SendEmailJob extends QuartzJobBean {
private SendEmailService sendEmailService;
private static final Log logger = LogFactory.getLog(SendEmailJob.class);
public void setSendEmailService(SendEmailService sendEmailService) {
if(this.sendEmailService == null)this.sendEmailService = sendEmailService;
}
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
logger.info("...開始執行任務...");
List<EmailAddress> addressList =this.sendEmailService.getEmailAddress("select * from EMAIL_ADDRESS_URL WHERE ENABLE=1");
for(EmailAddress emailAddress:addressList){
try {
boolean flag =this.sendEmailService.sendMail(emailAddress, null);
if(flag){
this.sendEmailService.updateEmailSuccess(emailAddress.getId());
}else{
this.sendEmailService.updateEmailFailed(emailAddress);
}
} catch (MessagingException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
logger.info("...任務執行完畢...");
}
}
其中用到了iReport,關於java中iReport開發,留給下次總計
本文介绍如何在Spring框架中使用Quartz调度框架实现邮件自动发送任务。通过配置Quartz与Spring集成,并创建定时任务及触发器,实现邮件发送功能。
1730

被折叠的 条评论
为什么被折叠?



