我在这里使用的Java计时器框架是由Java开发人员Tom White构建的一个简单通用的计划框架,以用于执行任意复杂的计划任务,他使我们实现灵活的计划策略成为可能。Java计时器框架的本身在这里不作过多的介绍,详细信息在IBM developerWorks中国网站。我们主要讨论如何利用Java计时器框架在Solaris平台来实现邮件的定时发送、JavaMail发送邮件的实现以及在Solaris平台上如何以后台方式运行整个邮件定时发送的应用。下载本文的源代码,参考具体实现。1.1  形成schedule.jar包schedule.jar包中的目录结构如下:我们将数据库的连接、日志、邮件和计划框架的通用类形成一个与具体应用要求无关的schedule.jar包。利用javac将编译生成的目标class文件存在当前目录的classes文件夹下,然后通过jar -cvf schedule.jar ./*命令生成schedule.jar包。1.1.1  Oracle数据库连接的建立位于db目录下,通过thin方式建立与Oracle的数据库连接,具体的实现参见《J2EE应用中与Oracle数据库的连接》一文。1.1.2  日志以后台方式定时运行的应用应特别注意日志的功能,因为只有通过分析详细的日志信息才能准确掌握应用的执行情况。在logs目录下为Logs.java文件,代码如下:package com.j2ee.logs;import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;public class Logs
{
private String logType="";
private String server="/schedule/logs/server.log";
private String task="/schedule/implements/nohup.out";
private SimpleDateFormat dateFormat = 
    new SimpleDateFormat("【 yyyy年MM月dd日 E a HH:mm:ss 】");

/**
* @param logType server task
*/
public Logs(String logType)
{
this.logType=logType;
} public void print(String msg)
{
try
{
String path="";
if (logType.equals("server"))
path=server;
if (logType.equals("task"))
path=task;
//
            BufferedWriter out
                = new BufferedWriter(new FileWriter(path,true));
String str=dateFormat.format(new Date());
if (logType.equals("task"))
out.newLine();
out.write(str,0,str.length());
out.write(msg,0,msg.length());
out.newLine();
out.close();
}
catch(Exception e)
{
System.out.println("Logs.print:"+e.getMessage());
}
}
};通过类中的构造器,可以生成两个日志文件:server.log和nohup.out。server.log用来记录计时器框架本身定时调度的日志信息,通过它来判断定时调度服务每天是否正常运行;nohup.out用来记录在具体应用中的调试信息,例如:在应用中通过System.out.println()输出的信息将记录在nohup.out文件中。1.1.3  邮件位于mail目录下,包括以下一些文件:1)Debug.java 发送邮件时的调试信息2)EMailContents.java 邮件的正文,为了使邮件接受者对收到的邮件有一个好的视觉效果,可以先写一个统一的HTML邮件模板,在模板中填充相应的内容。EmailContents类完成这一功能。效果如下:3)Mailer.java 发送邮件的主方法。它调用MailThread类中的方法创建一个发送邮件的线程。4)MailThread.java 发送邮件线程类。它调用MailHelper中的方法来完成发送邮件的工作。5)MailHelper.java 发送邮件的实现类。在类的createAndSendMail方法中包括了发送邮件一系列必须的过程,它可以完成一些邮件的正文、附件、抄送、回执等功能。在邮件的实现中用到了两个jar包:mail.jar和activation.jar。1.1.4  计划框架计划框架的详细内容可以通过本文前面提供的连接去详细了解,本文该部分的代码也出自IBM网站。1.2  邮件定时发送的实现这部分主要用到前面schedule.jar中的类来实现与具体应用要求相适应的应用。在implements目录下有三个类:1)ScheduleTask.java 包含一个main方法,在本例中"每天计划3点开始执行计划好的任务"。2)ScheduleThread.java 线程类,在该类的run方法中,可以添加不同类型的计划定时执行的任务类来完成不同的定时执行的任务,在本例中调用了Mails类中的sendMail方法来定时发送邮件。3)Mails.java 按照一定的业务逻辑规则实现邮件的发送。1.3  邮件定时发送应用的运行包括应用的启动和停止,在Solaris上我们可以编写两个脚本:start和stop来完成该工作。1.3.1  Start脚本Start脚本内容如下:echo '************************************************************'
CLASSPATH=.:/schedule/implements/jar/schedule.jar:
/schedule/implements/jar/classes12.zip:
/schedule/implements/jar/mail.jar:/schedule/implements/jar/activation.jar
export CLASSPATH
echo 'set schedule running environment success.'
nohup java com.j2ee.implement.ScheduleTask &
echo 'start schedule task success.'
echo 'view logs:'
echo '  /schedule/implements/nohup.out'
echo '  /schedule/logs/server.log'
date >> /schedule/logs/server.log
echo '计划框架成功启动' >> /schedule/logs/server.log
echo '************************************************************'这里有两个关键点:CLASSPATH的设置和nohup运行方式。在CLASSPATH中必须提供用到的所有jar包,多个jar包用":"分隔;"&"表示以后台方式运行,"nohup"使应用的运行不依赖于当前的会话,如果不以"nohup"方式的话,即" java com.j2ee.implement.ScheduleTask &",当你关闭你当前的会话时,应用将终止运行。可以使用"ps -ef | grep java"来查看应用运行的进程号。当然也可以通过手工交互的方式完成上述步骤来运行应用。1.3.2  Stop脚本Stop脚本内容如下:echo '************************************************************'
ps -e | grep java >> ps.out
kill -9 `cut -c 2-6 ps.out`
rm ps.out
date >> /schedule/logs/server.log
echo '计划框架成功停止' >> /schedule/logs/server.log
echo 'stop schedule task success.'
echo '************************************************************'该脚本中主要通过" ps -e | grep java"命令将输出信息重定向到"ps.out"文件中,在从文件中获得进程号,然后将它kill掉。同样也可以通过手工的方式将它kill。