解决方案 »
- java filter过滤admin下的jsp文件,web.xml该怎么写?
- 大神们,出现问题了,java一个判断语句居然总是正确的
- Hibernate中sql安全问题
- java c++ 进行socket通信对数据包的组装和拆分问题
- 很简单 进来的帮我看看
- java新手求教validate的问题,请用过validate框架的前辈们帮帮忙
- velocity中模版不用文件是否可行
- rest api 类,什么时候初始化?
- 谁有Tapestry + spring + hibernate开发的程序,给我发一下部分源码~~谢谢!
- Axis2 WebService如何输出自定义XML格式
- poi word07 表格问题
- 朋友们 ,帮帮忙,有个问题困扰我
更简单的是我多建几个job!但是别人不愿意啊!!!他非要弄成可配置的!
目前又遇到了一个问题!
就是执行过期时间的问题!
比如,我数据库有四个时间:
0 30 9 * * ?
0 31 9 * * ?
0 32 9 * * ?
0 33 9 * * ?
分别是早上九点半到九点三十四去执行,当执行到九点33的时候我获取到数据库中九点30的哪一条执行时间记录并setCronExpression(0 30 9 * * ?)这个时候系统时间已经到九点三十三分零几秒了,按理说他已经过了执行时间了,为什么quartz还要去执行呢,而且顺带31,32,33又执行,进入了死循环!
我的Spring配置文件:<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 被执行类 -->
<bean id="testQuarzt" class="cmcc.gz.pmp.timetest.service.ScheduleInfoService">
<property name="scheduler" ref="schedulerFactory" />
</bean> <!-- 将testQuarzt注入到job中 -->
<bean id="testQuartzJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testQuarzt" />
<property name="targetMethod" value="resetJob" />
<property name="concurrent" value="false" />
</bean> <!-- 将job注入到定时触发器 -->
<bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="testQuartzJob" />
<property name="cronExpression">
<value>0/10 * * * * ?</value>
</property>
</bean> <!-- 将触发器注入任务工程 -->
<bean id="schedulerFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="testTrigger" />
</list>
</property>
</bean>
</beans>我的任务类:import java.text.ParseException;import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.CronTriggerBean;import cmcc.gz.pmp.timetest.db.domain.Job;
import cmcc.gz.pmp.timetest.db.mapper.JobMapper;/**
*
* 类描述:时间任务调度测试方法
* @author 胡汉三
* 创建时间:2014-5-26 下午6:11:55
*
*/
public class ScheduleInfoService {
@Autowired
private JobMapper mapper;
private Scheduler scheduler;
// 设值注入,通过setter方法传入被调用者的实例scheduler
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void resetJob() throws SchedulerException, ParseException{
Job j = mapper.findJob();
j.setFlag(1);
mapper.updateTimeTask(j);
String cronExpression = j.getJob();
System.out.println(cronExpression);
Job job = new Job();
if(j.getType()!=3){
job.setId(j.getId()+1);
}else{
job.setId(1);
}
job.setFlag(0);
mapper.updateTimeTask(job);
// 运行时可通过动态注入的scheduler得到trigger,注意采用这种注入方式在有的项目中会有问题,如果遇到注入问题,可以采 取在运行方法时候,获得bean来避免错误发生。
CronTriggerBean trigger = (CronTriggerBean)scheduler.getTrigger("testTrigger",Scheduler.DEFAULT_GROUP);
String originConExpression = trigger.getCronExpression();
// 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob
if(!originConExpression.equalsIgnoreCase(cronExpression)){
trigger.setCronExpression(cronExpression);
scheduler.rescheduleJob("testTrigger", Scheduler.DEFAULT_GROUP, trigger);
}
/** 执行任务 **/
test();
}
/**
* 执行任务
*/
public void test(){
System.out.println("XML任务进行中...");
}
}
try {
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
JobDetail jobDetail = new JobDetail("CronTirgger",Scheduler.DEFAULT_GROUP, CronTirgger.class);
jobDetail.getJobDataMap().put(" type ", " FULL ");
CronTrigger trigger = new CronTrigger("CronTirgger",Scheduler.DEFAULT_GROUP);
/**这里你可以写一个专门获取表达式的工具类 */
trigger.setCronExpression("0 40 8 * * ?");
sched.scheduleJob(jobDetail, trigger);
// sched.start();
} catch (Exception e) {
e.printStackTrace();
} }
trigger.setCronExpression(cronExpression);
scheduler.rescheduleJob("testTrigger", Scheduler.DEFAULT_GROUP, trigger);
你外面的是resetJob,会不会造成里面的rescheduleJob,导致死循环。
是否可以将时间距离设置大一点,然后debug下
按照你的提示,我把时间间距设置增大!
测试的时候出现了问题、原xml配置将初始执行时间改为:0/1 * * * * ?:
程序代码:import java.text.ParseException;
import java.util.Date;import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.CronTriggerBean;import cmcc.gz.pmp.timetest.db.mapper.JobMapper;
import cmcc.gz.pmp.util.CommonDate;/**
*
* 类描述:时间任务调度测试方法
* @author 胡汉三
* 创建时间:2014-5-26 下午6:11:55
*
*/
public class ScheduleInfoService {
@Autowired
private JobMapper mapper;
private Scheduler scheduler;
// 设值注入,通过setter方法传入被调用者的实例scheduler
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void resetJob() throws SchedulerException, ParseException{
Object j = mapper.findJob(CommonDate.getTimeNow(new Date()));
// 运行时可通过动态注入的scheduler得到trigger,注意采用这种注入方式在有的项目中会有问题,如果遇到注入问题,可以采 取在运行方法时候,获得bean来避免错误发生。
CronTriggerBean trigger = (CronTriggerBean)scheduler.getTrigger("testTrigger",Scheduler.DEFAULT_GROUP);
String originConExpression = trigger.getCronExpression();
// 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob 也不需要去执行任务
if(!originConExpression.equalsIgnoreCase(j.toString())){
//如果不是系统启动时的任务,就去执行它
if(!originConExpression.equalsIgnoreCase("0/1 * * * * ?")){
/** 执行任务 **/
test();
}
System.out.println(j.toString());
trigger.setCronExpression(j.toString());
scheduler.rescheduleJob("testTrigger", Scheduler.DEFAULT_GROUP, trigger);
}
}
/**
* 执行任务
*/
public void test(){
System.out.println("XML任务进行中...");
}
}数据库值:
0 30 9 * * ?
0 30 11 * * ?
0 30 16 * * ?
测试时,当我把我的系统时间改为九点29的时候等到30就会执行,结果跟过程都正常,
更改到十一点半正常,更改到十六点半正常,当我更改到第二天九29的时候,执行就出错了:05-29 09:30:00 ERROR com.jolbox.bonecp.ConnectionHandle.PossiblyBroken(ConnectionHandle.java:297): Database access problem. Killing off all remaining connections in the connection pool. SQL State = 08S01
05-29 09:30:00 ERROR org.quartz.core.JobRunShell.run(JobRunShell.java:232): Job DEFAULT.testQuartzJob threw an unhandled Exception:
org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'resetJob' on target class [class cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3] failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
05-29 09:30:00 ERROR org.quartz.core.JobRunShell.run(JobRunShell.java:232): Job DEFAULT.testQuartzJob threw an unhandled Exception:
org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'resetJob' on target class [class cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3] failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureThe last packet successfully received from the server was 70,495,036 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:308)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:111)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureThe last packet successfully received from the server was 70,495,036 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:240)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
at cmcc.gz.platform.log.aop.CmccLogMonitorAspect.doServiceAround(SourceFile:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3.resetJob(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:299)
... 3 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureThe last packet successfully received from the server was 70,495,036 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.]
at org.quartz.core.JobRunShell.run(JobRunShell.java:234)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'resetJob' on target class [class cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3] failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureorg.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3.resetJob(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:299)
... 3 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failureThe last packet successfully received from the server was 70,495,036 milliseconds ago. The last packet sent successfully to the server was 1 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3102)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618)
at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5000)
at com.jolbox.bonecp.ConnectionHandle.setAutoCommit(ConnectionHandle.java:1063)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:223)
... 29 more
Caused by: java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002)
... 37 more
我刚刚查看了一下,在正常的时候,我的死连数是110.
然后在我改为第二天九点29,也就是要执行出错的时候,死连数就增长了!
mysql> show status like '%Aborted_clients%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| Aborted_clients | 110 |
+-----------------+-------+
1 row in setmysql> show status like '%Aborted_clients%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| Aborted_clients | 118 |
+-----------------+-------+
1 row in set哎,求指点!
Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。
它默认是8小时,我们手动改大一些,在测试就通过了!
查看:show global variables like 'wait_timeout';
修改:set global wait_timeout=86999;OK......告一段落!!!
mysql数据库表:DROP TABLE IF EXISTS `test_time_task`;
CREATE TABLE `test_time_task` (
`status` int(11) DEFAULT NULL COMMENT '状态:0为正常,1为禁用',
`job` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '执行时间',
`id` int(11) DEFAULT NULL COMMENT '编号'
) ENGINE=InnoDB DEFAULT CHARSET=utf-8;
-- ----------------------------
-- Records of test_time_task
-- ----------------------------
INSERT INTO `test_time_task` VALUES ('0', '0 30 9 * * ?', '1');
INSERT INTO `test_time_task` VALUES ('0', '0 30 11 * * ?', '2');
INSERT INTO `test_time_task` VALUES ('0', '0 30 16 * * ?', '3');查询语句其中的#{hourMinute}为查询条件,格式——'12:11':select case when (select job
from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
where
str_to_date( CONCAT(hour,':',minute),'%k:%i')> str_to_date( #{hourMinute} ,'%k:%i') order by str_to_date(hour,'%k') LIMIT 1) is null then
(select job
from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
order by str_to_date( CONCAT(hour,':',minute),'%k:%i') LIMIT 1) else
(select job
from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
where
str_to_date( CONCAT(hour,':',minute),'%k:%i')> str_to_date( #{hourMinute} ,'%k:%i') order by str_to_date(hour,'%k') LIMIT 1) end
Spring配置文件:<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 被执行类 -->
<bean id="testQuarzt" class="cmcc.gz.pmp.timetest.service.ScheduleInfoService">
<property name="scheduler" ref="schedulerFactory" />
</bean> <!-- 将testQuarzt注入到job中 -->
<bean id="testQuartzJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testQuarzt" />
<property name="targetMethod" value="loadJob" />
<property name="concurrent" value="false" />
</bean> <!-- 将job注入到定时触发器 -->
<bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="testQuartzJob" />
<property name="cronExpression">
<value>0/1 * * * * ?</value>
</property>
</bean> <!-- 将触发器注入任务工程 -->
<bean id="schedulerFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="testTrigger" />
</list>
</property>
</bean>
</beans>
java程序代码:
import java.text.ParseException;
import java.util.Date;import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.CronTriggerBean;import cmcc.gz.pmp.timetest.db.mapper.JobMapper;
import cmcc.gz.pmp.util.CommonDate;/**
*
* 类描述:时间任务调度测试方法
* @author 胡汉三
* 创建时间:2014-5-26 下午6:11:55
*
*/
public class ScheduleInfoService {
@Autowired
private JobMapper mapper;
private Scheduler scheduler;
// 设值注入,通过setter方法传入被调用者的实例scheduler
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void loadJob() throws SchedulerException, ParseException{
Object j = mapper.findJob(CommonDate.getTimeNow(new Date()));
// 运行时可通过动态注入的scheduler得到trigger,注意采用这种注入方式在有的项目中会有问题,如果遇到注入问题,可以采 取在运行方法时候,获得bean来避免错误发生。
CronTriggerBean trigger = (CronTriggerBean)scheduler.getTrigger("testTrigger",Scheduler.DEFAULT_GROUP);
String originConExpression = trigger.getCronExpression();
// 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob 也不需要去执行任务
if(!originConExpression.equalsIgnoreCase(j.toString())){
//如果不是系统启动时的任务,就去执行它
if(!originConExpression.equalsIgnoreCase("0/1 * * * * ?")){
/** 执行任务 **/
test();
}
System.out.println(j.toString());
trigger.setCronExpression(j.toString());
scheduler.rescheduleJob("testTrigger", Scheduler.DEFAULT_GROUP, trigger);
}
}
/**
* 执行任务
*/
public void test(){
System.out.println("XML任务进行中...");
}
}