假设以下组件树:
- A
- B
- C
A 有一个私有(private)字段(称为过滤器),并且对过滤器的引用传递给 B 和 C。 在 B 类中,过滤器的属性是通过 AjaxLink 修改的(因此没有页面刷新)。 我(通过)日志记录看到,每次 ajax 调用后,wicket 都会序列化 A、B 和 C。
现在,一切正常,单击 B 中的 AjaxLinks 将很好地更新过滤器,并将刷新 C 并在 C 中显示正确的信息(基于过滤器)。
但是,假设如果单击 B 中的 AjaxLink,这会将过滤器的属性更新为(例如)值 2。之后我按 F5,它仍然有效,并且页面(及其中的所有组件)被反序列化(并且之后再次连载)。然后,我单击 AjaxLink,将上述属性的值更改为 3;这仍然工作正常。但是,如果我执行页面刷新 (F5),则该属性的值会突然再次变为 2。
似乎在页面刷新时(当 wicket 将从磁盘加载页面时),wicket 正在反序列化旧版本的过滤器。
原理图:
- 页面初始加载:
=> filter.value = 3 -> 序列化 - Ajax链接:
=> filter.value = 2 -> 序列化 - 页面刷新:
=> filter.value = 2 -> 反序列化/序列化 - Ajax链接:
=> filter.value = 3 -> 序列化 - 页面刷新:
=> filter.value = 2 -> 反序列化/序列化
似乎在操作 5 上,操作 4 之后的序列化版本被忽略,而操作 3 之后的序列化版本被加载。
希望有一个原因、解释,如果可能的话还有解决方案:-)
代码
public class A extends Panel { //creates the filter and passes the reference on
Filter filter = new Filter(TypeEnum.ALL);
public A(final String id) {
super(id);
add(new B("filterPanel", filter));
add(new C("datatable", filter));
}
public class B extends Panel { //updates the filter
Filter filter;;
public B(final String id, Filter filter) {
super(id);
this.filter = filter;
add(new IndicatingAjaxLink<Void>("other") {
@Override
public void onClick(AjaxRequestTarget target) {
filter.setType(TypeEnum.OTHER);
...
}
};
}
}
public class C extends Panel { //uses the filter
Filter filter;;
public C(final String id, Filter filter) {
super(id);
this.filter = filter;
}
public void populateRepeatingView() {
final List<? extends WallEntry> result = service.find(filter);
...
}
}
代码已被简化,我只保留了(我认为)相关的内容。
更新
如果我在页面类中添加以下内容,那么它就可以工作:
@Override
public boolean isVersioned() {
return false;
}
但是不确定这会产生什么影响以及为什么它会起作用。该页面不再序列化(反序列化)了吗?
更新
我将以下内容添加到我的 Page 类中:
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
System.err.println("Writing " + this + something to print out the type of the filter);
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
System.err.println("Reading " + this + something to print out the type of the filter);
}
第一次加载页面时会打印(实际上打印了5次,不确定是否正常): 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = ALL
当我单击 AjaxLink 'ALL'(这将更新过滤器)时,它仍然会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = ALL
当我单击 AjaxLink“讨论”(这将更新过滤器)时,它仍然会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = 讨论
当我刷新页面 (F5) 时,pageid 会更新: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 1,渲染计数 = 2]:类型 = 讨论
当我单击 AjaxLink 'ALL'(将更新过滤器)时,它会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 1,渲染计数 = 1]:类型 = ALL
到目前为止一切顺利,但是当我现在刷新页面(F5)时,会打印出以下内容: 阅读 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = 讨论 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 2,渲染计数 = 2]:类型 = 讨论
网址永远不会改变,它保持 http://.../?0
因此,它反序列化 id 为 0 的页面,尽管最后一个已知的页面 id 为 1,并且对版本 1 所做的所有更改都将被忽略(在本例中,将类型从 DISCUSSIONS 切换为 ALL)。
为此在 wicket jira 中创建了一个问题:https://issues.apache.org/jira/browse/WICKET-4360
最佳答案
刷新页面时观察浏览器的 url。它可能包括 Wicket 页面版本,因此当您第二次刷新时,页面的特定版本将被反序列化。
由于您将过滤器保留在页面中,因此它会与其包含的组件一起被序列化/反序列化。
解决方案是将过滤器放入 session 中。
关于java - Wicket 序列化/反序列化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8985785/