我们正在使用Wicket Wizard
组件。在向导的最后一步,我们发现如果用户快速单击完成按钮,则Wicket会多次调用我们的onFinish()
方法。这给我们带来了问题。
有趣的是,问题出现在我们尝试过的所有浏览器(IE,Chrome)中,但在Firefox中却没有。此浏览器似乎检测到多次单击,并且只向服务器发送一次单击事件。
问题是,我们可以做些什么来阻止这种情况?
从查看Wicket框架代码,我可以看到导航按钮包含在WizardButtonBar
中,而FinishButton
正在处理onClick
事件,但我不确定是否正确重写或控制此行为的方法,并以某种方式检测多个onClick
事件
答案 0 :(得分:0)
你似乎没有使用Ajax,是吗?
如果你这样做,你可以添加面纱 - 例如通过覆盖#getAjaxIndicatorMarkupId()
- 任何双重提交都将被阻止。其他好处:如果用户在向导完成后按下后退按钮,浏览器将离开向导,用户无法再次完成。
对于非Ajax请求,您必须将自己的面纱JavaScript添加到按钮中
为防止用户再次返回并完成向导,您可以使用基于令牌的解决方案:
在向导启动时获取一个令牌(可能只是一个计数器)。向导完成后,将令牌标记为已消耗(例如,将其存储在域对象中)
在向向导发出的每个请求中,您可以检查令牌是否仍然有效 - 如果没有,则将用户重定向到另一个页面,说明向导已经完成。
答案 1 :(得分:0)
安德鲁非常友好地为我提交了原始问题。我确实尝试过这样做(几乎和你的建议一样):
class MyWizard extends Wizard {
private Integer finishPressed = -1; // deliberately set an invalid value to start with
public MyWizard() {
finishPressed = 0; // only place where finishedPressed is set to 0
log.info( "init: finishPressed={}", finishPressed );
}
@Override
public void onFinish() {
log.info( "begin: finishPressed={}", finishPressed );
if ( ! finishPressed ) {
finishPressed += 1;
// do onFinish actions ...
}
log.info( "end: finishPressed={}", finishPressed );
}
}
但是,我发现onFinish()被调用了很多次,因为我按下了Finish按钮,但是每次finishPressed进入方法时都是0,而不是计数递增。
注意:我只看到" init:finishPressed = 0" 一次在日志中。我不知道它是如何重置为0.但是,我确实注意到onFinish()调用每次都由不同的线程处理。但正如所说,构造函数(唯一的地方finishPressed设置为0)只被调用一次。
只有将finishPressed声明为静态(这显然会导致真实实时操作出现问题)才能看到finishPressed按预期递增。