java - Wicket 序列化/反序列化问题

标签 java serialization wicket wicket-1.5

假设以下组件树:

  • 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 正在反序列化旧版本的过滤器。

原理图:

  1. 页面初始加载:
    => filter.value = 3 -> 序列化
  2. Ajax链接:
    => filter.value = 2 -> 序列化
  3. 页面刷新:
    => filter.value = 2 -> 反序列化/序列化
  4. Ajax链接:
    => filter.value = 3 -> 序列化
  5. 页面刷新:
    => 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); 
} 
  1. 第一次加载页面时会打印(实际上打印了5次,不确定是否正常): 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = ALL

  2. 当我单击 AjaxLink 'ALL'(这将更新过滤器)时,它仍然会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = ALL

  3. 当我单击 AjaxLink“讨论”(这将更新过滤器)时,它仍然会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 0,渲染计数 = 1]:类型 = 讨论

  4. 当我刷新页面 (F5) 时,pageid 会更新: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 1,渲染计数 = 2]:类型 = 讨论

  5. 当我单击 AjaxLink 'ALL'(将更新过滤器)时,它会打印: 编写 [页面类 = com.bnpp.ecom.homepage.web.Homepage,id = 1,渲染计数 = 1]:类型 = ALL

  6. 到目前为止一切顺利,但是当我现在刷新页面(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/

相关文章:

websocket - 通过推送消息触发重新绘制 Wicket 口组件

java - 错误: Not detached model found

java - Logback RollingFileAppender 没有写入正确的文件

c# - 为所有继承自基类型的类设置自定义 MongoDB BsonSerializer

java - Kryo 反序列化失败,返回 "KryoException: Buffer underflow"

ajax - 使用 Wicket.ajax.post 发布大量数据

java - block 中 Java 变量的作用域是什么?

java - 使用 Java 中的单一模式填充表

java - 为什么@ApiModelProperty "name"属性没有效果?

c# - 为什么 C# 空条件运算符不适用于 Unity 可序列化变量?