spring+ Quartz冲突问题解决

Exception in thread "main" java.lang.NoSuchMethodError: 
org.apache.commons.collections.SetUtils.orderedSet(Ljava/util/Set;)Ljava/util/Set;
 at org.quartz.JobDetail.<init>(JobDetail.java:85)

这个问题困扰了我N久,幸好看到了这篇文章,写的很详细,转载下.
 
假设你是一个J2EE程序员,你正在使用struts2+spring2+hibernate3的时尚标准组合来开发一个项目。某天,你的项目经理告诉 你,当前项目需要开发一个新功能,需要系统来定时来执行一段代码,比如每天大半夜定时进行前一天的数据统计并且插入数据库。如果你部署的系统是Linux 并且你熟悉crontab而且你打算那么麻烦地去干,我当然没话可说。否则在你google和baidu了一会儿之后,你必然会想到可以使用著名的 quartz来和spring集成起来做这件事。 

比如,先把需要干的活儿写在一个类的一个方法里面:
Java代码  收藏代码
public class ScheduleWorker {  
public void doDailyWork() {  
System.out.println("今日统计完毕!");  
}  
}   
 

然后,配置spring的applicationContext.xml如下:
Xml代码  收藏代码
<bean name="scheduleWorker" class="test.ScheduleWorker">  
</bean>  
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
<property name="targetObject" ref="scheduleWorker" />  
<property name="targetMethod" value="doDailyWork" />  
<property name="concurrent" value="false" />  
</bean>  
  
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
<property name="jobDetail" ref="jobDetail" />  
<!-- 每天零点 -->  
<property name="cronExpression">  
<value>0 0 * * * ?</value>  
</property>  
</bean>  
  
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">  
<property name="triggers">  
<list>  
<ref bean="cronTrigger" />  
</list>  
</property>  
</bean>   
 
然 后编译上传(别忘了上传更新的applicationContext.xml还有quartz.jar,一般都在spring解开的包的 lib/quartz目录下面)。你重新启动你的tomcat(也可能是resin或者其他什么东西),然后,不出意外地,发现如下错误: 



ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobDetail' defined in ServletContext resourc 
e [/WEB-INF/classes/applicationContext-service.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodErr 
or: org.apache.commons.collections.SetUtils.orderedSet(Ljava/util/Set;)Ljava/util/Set; 
如果你经验比较丰富,你会去找你部署的服务器的WEB-INF/lib下面是不是存在commons-collections的jar包,然后你很惊奇地发现它的确在那里,你会很困惑。 

如 果你经验十分丰富,你知道了commons-collections.jar的确存在于classpath里面,你知道引起 NoSuchMethodErr的原因很可能是部署服务器上的commons-collections.jar的版本过低,在quartz调用的时候不存 在而导致的,于是你会去检查WEB-INF/lib下面的commons-collections.jar的版本,然后你还是会很惊奇地发现它的版本是 3.2,并且在这个jar包里面的确存在org.apache.commons.collections.SetUtils这个类,并且方法 orderedSet也存在,你还是会很困惑。 

如果你经验非常丰富,你知道了引起上面这种情况的原因是系统的classloader 先加载了其他地方低版本的commons-collections里面的 org.apache.commons.collections.SetUtils类,导致WEB-INF/lib下面的commons- collections.jar里面的同名类没有被加载所导致的。于是你就到处去找另外的commons-collections.jar,在WEB- INF/lib你可能会找到一个,包括common/lib等等地方,如果你是jdk6,你还有可能在jdk的ext目录下找到。删掉老版本的 commons-collections.jar,重启tomcat,发现问题依旧,你继续找。但是皇天不负有心人,你啥都没找到,整个jdk和整个 tomcat下面,你整个搜索了一番,只有这么一个commons-collections.jar。你依然会很困惑。 

不卖关子了。解决问题的办法:删除WEB-INF/lib/checkstyle-all.jar,重新启动tomcat,问题解决。 

在 hibernate3的lib目录下,存在commons-collections-2.1.1.jar和checkstyle-all.jar,一般我 们都是直接上传到WEB-INF/lib,前者不必说,版本太老而被classloader先加载了,按说删了问题应该解决了,但是为什么必须删掉 checkstyle-all.jar问题才能正式解决呢。拿WinRAR打开checkstyle-all.jar一看你就知道了,里面赫然有 org.apache.commons.collections.SetUtils这个类,并且,它是老版本的! 

这也太可恶了,明明 叫checkstyle-all.jar,里面为啥还包含commons-collections的东西……而且还是老调牙的版本。另外,如果你觉得 checkstyle-all.jar或许还有点什么用处,可以用WinRAR解开之后把commons-collections的包和类去掉,然后重新 打包上传。 

其实问题的根源在于:hibernate3使用老版本(2.1.1)的commons-collections及包含它的 checkstyle-all.jar,而spring2.5使用新版本(3.2)的commons-collections以及需要3.2版本 commons-collections的quartz。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用Spring Quartz实现定时任务时,如果需要修改定时时间而不重启服务,可以考虑以下几种方式: 1. 使用Quartz的动态定时任务更新功能: Quartz提供了动态修改定时任务的功能,可以通过更新Cron表达式来实现修改定时时间。首先,在配置文件中设置定时任务的Cron表达式为一个变量,然后在代码中通过调用Quartz的API读取配置文件的变量,并更新定时任务的Cron表达式。通过这种方式,不需要重启服务即可修改定时时间。 2. 使用数据库表保存定时任务配置参数: 可以将定时任务的配置参数,如定时时间、执行类等保存在数据库表中。然后在代码中通过查询数据库表的方式动态获取定时任务的配置参数。当需要修改定时时间时,只需更新数据库表中的相应字段,代码会动态读取到新的定时时间并生效,而不需要重启服务。 3. 使用Spring的动态Bean注册功能: 在项目启动时,通过编程的方式动态注册定时任务的Bean。将定时任务的配置属性作为参数传入Bean,当需要修改定时时间时,通过修改Bean的相关属性值来实现。Spring会自动重新加载Bean的定义,并根据新的配置参数重新创建定时任务对象,从而实现修改定时时间而不重启服务。 综上所述,使用Quartz的动态定时任务更新功能、数据库表保存定时任务配置参数或者Spring的动态Bean注册功能,都可以实现在不重启服务的情况下修改定时时间。根据实际项目需求和技术架构选择合适的方式即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值