Wicket应用程序、序列化和Java计时器
因此,我在序列化、Wicket和多线程项目方面的经验有限,所以请耐心等待 从本质上说,我的web应用程序类实例化了一个POJ(parentObject),它创建了一个新的计时器,并实例化了几个也包含计时器的ChildObject。这些子对象存储在parentObject类的列表中。wicket应用程序中的页面需要访问parentObject,因此我将其设置为可访问:Wicket应用程序、序列化和Java计时器,java,serialization,timer,wicket,Java,Serialization,Timer,Wicket,因此,我在序列化、Wicket和多线程项目方面的经验有限,所以请耐心等待 从本质上说,我的web应用程序类实例化了一个POJ(parentObject),它创建了一个新的计时器,并实例化了几个也包含计时器的ChildObject。这些子对象存储在parentObject类的列表中。wicket应用程序中的页面需要访问parentObject,因此我将其设置为可访问: public Object getParentObject { return this.parentObject; } 在
public Object getParentObject
{
return this.parentObject;
}
在每个页面中检索,如下所示:
((MyApplication)Application.get()).getParentObject()
目前的问题是parentObject和ChildObject的timertask不再像应该的那样每分钟都被调用一次。我的日志会拾取parentObject的第一个开始,但是日志消息不会再次输出,表明父对象的timertask的run()方法不会每分钟执行一次
编辑:添加了更多的代码,使问题更加清楚
public class childObject implements Serializable
{
private transient NamedParameterJdbcTemplate njt;
private transient Timer timer;
public childObject(DataSource ds)
{
this.njt = new NamedParamterJdbcTemplate(ds);
}
public void start()
{
timer = new Timer();
timer.schedule(new TimerTask(){
public void run()
{
//do some stuff that is never happening
}
}, 0, 60000);
}
}
public class ParentObject implements Serializable
{
private DataSource ds;
private List<ChildObject> childObjects;
private transient Timer;
public ParentObject(DataSource ds)
{
this.ds = ds;
//add some stuff to childObjects
timer = new Timer();
timer.schedule(new TimerTask(){
public void run()
{
for(some condition)
{
//Do some stuff
if(/*condition is met*/)
{
childObjects.get(i).start();
}
}
}
}, 0, 60000);
}
}
public MyApplication extends WebApplication
{
private ParentObject object;
private DataSource ds;
public void init()
{
super.init();
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
ds = (DataSource) context.getBean("dataSource");
parentObject = new ParentObject(ds);
}
}
公共类childObject实现可序列化
{
私有瞬态名称参数jdbctemplate njt;
专用瞬态定时器;
公共子对象(数据源ds)
{
this.njt=新名称参数JDBCTemplate(ds);
}
公开作废开始()
{
定时器=新定时器();
timer.schedule(新TimerTask(){
公开募捐
{
//做一些从未发生过的事情
}
}, 0, 60000);
}
}
公共类ParentObject实现了可序列化
{
私有数据源ds;
私有列表对象;
专用瞬态定时器;
公共ParentObject(数据源ds)
{
这是1.ds=ds;
//向childObjects添加一些内容
定时器=新定时器();
timer.schedule(新TimerTask(){
公开募捐
{
为了(某些条件)
{
//做点什么
如果(/*条件满足*/)
{
get(i).start();
}
}
}
}, 0, 60000);
}
}
公共MyApplication扩展了WebApplication
{
私有父对象;
私有数据源ds;
公共void init()
{
super.init();
ApplicationContext context=new ClassPathXmlApplicationContext(“/ApplicationContext.xml”);
ds=(DataSource)context.getBean(“DataSource”);
parentObject=新的parentObject(ds);
}
}
根据您的问题描述,我认为您可以将ParentObject直接绑定到组件,而不是绑定对ParentObject的引用。会话范围对象(所有页面、组件和模型都是有效的)的序列化/反序列化将创建这些“新”实例(即使它们是原始父对象的反序列化副本)
虽然您没有显示太多代码,但我怀疑您会这样做:
public MyPage() {
Object parentObject = ((MyApplication)Application.get()).getParentObject();
add(new Label("timer", new PropertyModel(parentObject, "time")));
}
这将父对象绑定到属性模型,并将父对象绑定到页面(通过标签组件)。你应该做的是:
public MyPage() {
add(new Label("timer", new PropertyModel(this, "application.parentObject.time")));
}
这会将页面绑定到自身,并指示属性模型动态地检索应用程序,从应用程序检索父对象,然后从父对象检索。这样,您就不会将对象绑定到页面层次结构,而是动态地检索它们
另一个选项是使用LoadableDetachableModel从应用程序检索父对象,并在呈现页面后将其分离
public class ParentObjectModel extends LoadableDetachableModel<ParentObject> {
@Override public ParentObject load() {
return ((MyApplication)Application.get()).getParentObject();
}
}
公共类ParentObjectModel扩展了LoadableDetachableModel{
@重写公共父对象加载(){
return((MyApplication)Application.get()).getParentObject();
}
}
请参阅。WicketApplication是Singleton,不会被序列化为页面或会话。感谢您的评论。我明白这一点,但我的计时器仍然没有按预期工作。我添加了一些伪代码来显示这种情况,你是说我应该将parentObject变量作为公共变量存储在应用程序中?这与使用访问器方法将其存储为私有变量有什么不同吗,因为这是我目前正在做的事情。我从来没有说过。Wicket足够聪明,可以使用私有字段和/或访问器。这就是房产模型的工作原理。谢谢你的建议。我编辑了这个问题,添加了一些更详细的代码。