我所做的是,当我第一次运行一个servlet(从jsp调用)时,在放入该服务的一个条目时,每天在conf file.i中运行一个调用程序,它将调用程序(servlet-每天为该服务运行并发送邮件10。
下面是我用来执行任务的代码。但问题是当我停止服务器时,调度程序停止并且没有任何反应
public class Schedule
{
public static final String CONF_PATH = "../webapps/selen/WEB-INF/scheduling.properties";
public static Properties schProps = null;
public static FileInputStream sis = null;
public static long period;
public static Timer timer = new Timer();
public static String servicename = null;
public static String keyValues = null;
public static String reValues[] = null;
public static String schedulingValue = null;
public static String service_url = null;
public static String browserlist = null;
public static String testType = null;
public static String mailCheacked = null;
public static String toaddr = null;
public static HttpServletRequest request = null;
public static HttpServletResponse response = null;
public static String serversURL = null;
public static String contextPath = null;
public static Date delay = null;
public void scheduleLoad(String serviceValue) throws Exception
{
try
{
schProps = new Properties();
sis = new FileInputStream(CONF_PATH);
schProps.load(sis);
servicename = SServlet.serviceName;
keyValues = schProps.getProperty(serviceValue);
reValues = keyValues.split(",");
String request = reValues[0];
String response = reValues[1];
schedulingValue = reValues[2];
service_url = reValues[3];
browserlist = reValues[4];
testType = reValues[5];
mailCheacked = reValues[6];
toaddr = reValues[7];
serversURL = reValues[8];
contextPath = reValues[9];
if(reValues[2].equals("Daily"))
{
Calendar cal =Calendar.getInstance();
cal.set(Calendar.HOUR,10);
cal.set(Calendar.MINUTE,20);
cal.set(Calendar.SECOND,0);
delay = cal.getTime();
period = 1000 * 60 * 60 * 24;
schedule();
}
else if(reValues[2].equals("Stop"))
{
stop();
}
}
catch(NullPointerException npe)
{
System.out.println("null point exception ");
}
finally
{
if(sis !=null)
{
sis.close();
}
}
}
public static void schedule()
{
MyTimerTask mt = new MyTimerTask(request,response,servicename,service_url,browserlist,mailCheacked,testType,schedulingValue,toaddr,serversURL,contextPath);
timer.schedule(mt,delay,period);
}
public static void stop()
{
timer.cancel();
}
}
class MyTimerTask extends TimerTask
{
public HttpServletRequest request;
public HttpServletResponse response;
public String servicename;
public String service_url;
public String browserlist;
public String mailCheacked;
public String testType;
public String schedulingValue;
public String toaddr;
public String serversURL;
public String contextPath;
public MyTimerTask(HttpServletRequest request,HttpServletResponse response, String servicename,String service_url,String browserlist,String mailCheacked,String testType,String schedulingValue,String toaddr,String serversURL, String contextPath)
{
this.request = request;
this.response = response;
this.servicename = servicename;
this.service_url = service_url;
this.browserlist = browserlist;
this.mailCheacked = mailCheacked;
this.testType = testType;
this.schedulingValue = schedulingValue;
this.toaddr = toaddr;
this.serversURL = serversURL;
this.contextPath = contextPath;
}
public void run()
{
SServlet sservlet = new SServlet();
sservlet.sServerloading(request,response,servicename,service_url,browserlist,mailCheacked,testType,schedulingValue,toaddr,false,1,serversURL,contextPath);
}
}
答案 0 :(得分:1)
JDK Timer在JVM中运行,而不是在操作系统中运行。它不是CRON或Windows调度程序。所以,当你停止服务器(Tomcat?JBoss?Glassfish?)时,你有效地停止了Timer所在的JVM,当然它不会再运行了。如果您想要一个独立于服务器运行的计时器(调度程序),则必须在它自己的JVM中启动它,或者使用java
命令作为独立的Java程序,或者在另一个服务器实例中启动它。
在旁注中,如果您对某些批评持开放态度,请对您的代码进行一些小评论:
尽可能避免混合静态和非静态上下文。您的Schedule类实例方法scheduleLoad()
大量使用静态成员变量进行有状态存储。变量要么仅用于执行方法(在这种情况下它们应该在该方法中声明),要么它们用于描述对象的状态(在这种情况下它们应该是类的私有实例成员)或者它们是全局常量或不可变全局变量(在这种情况下,它们应声明为static final)。这些例外情况存在,但不太常见。
如果成员变量public
不同,则避免声明成员变量final
。坚持JavaBean模式,使用getter和setter。如果变量实际上是一个常数,那么它应该是public static final
。
避免使用超出范围的类或参数。例如,您的MyTimerTask
使用HttpServletRequest
和HttpServletResponse
作为成员变量和方法参数。这没有任何意义,因为MyTimerTask
未在servlet请求的范围内使用(并且随后将始终为null,对吧?)。或者,如果确实如此,如果您在某个servlet中显式设置Schedule
的静态成员然后调用scheduleLoad()
,请参阅我关于不正确使用静态上下文的第一点。您的代码不是线程安全的,并且使用Schedule
的任何servlet的并发调用都会产生不可预测的行为。
更新:
我很难知道从哪里开始,因为我不确定你在Java中的专业水平。如果您不熟悉如何执行独立的Java应用程序,我建议您参加一些教程。 Oracle在http://download.oracle.com/javase/tutorial/有一堆。 http://download.oracle.com/javase/tutorial/getStarted/index.html是一个很好的起点,因为它引导您使用main
方法完成一个非常基本的“hello world”类型应用程序,以及如何使用java
命令执行它,以及一些常见的错误和问题。
一旦你想出了这一切,花几分钟时间弄清楚你的应用程序应该做什么,它需要哪些资源以及是否需要调用任何“外部”系统。你提到它应该“执行一个servlet来发送邮件”。这是否意味着它必须调用特定的servlet,或者它只是发送邮件,而这正是你所追求的。在这种情况下,也许您可以将所有邮件发送逻辑移动到您的独立程序?如果没有,您将不得不使用http请求调用servlet(就像浏览器一样)。有许多现有的框架可以做这样的事情。 Apache HttpClient非常受欢迎。
答案 1 :(得分:0)
如果停止程序,它将无效。这不是一个bug。这是一个功能。顺便说一下,如果关闭计算机,也没有任何事情发生:)。
但是,如果你的任务是如何使我的计划任务更加健壮,例如如何使任务在服务器停止然后再次启动时继续工作,你必须在调度程序的某个状态,即在你的情况下最后一次执行任务。您可以自己实现:创建特殊文件并将数据存储在那里。您可以使用跨平台纯Java Preferences API来执行此操作:数据将存储在Unix中的文件系统和Windows中的Registry中。你也可以在DB中保存状态。
但您可以使用已实现此功能的其他产品。最受欢迎和最着名的是Quartz。
但是Quartz仍然需要一些java进程才能启动并运行。如果您希望能够运行您的任务,即使没有运行任何Java进程,也可以使用平台相关工具:用于Unix的cron tab
和用于Windows的调度程序API(可通过VBScript,JScript,命令行访问)。
Unix有cron