我怎样才能让 Wicket 的“AjaxLink"无国籍? [英] How can I make Wicket's "AjaxLink" Stateless?

查看:33
本文介绍了我怎样才能让 Wicket 的“AjaxLink"无国籍?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 Wicket Web 应用程序,它将不得不处理大量并发请求.我已经设置了一个测试环境和一些 jmeter 脚本来进行负载测试,我注意到如果我将大多数页面设为无状态,我可以减少应用程序的 CPU 和内存占用.

I am building a Wicket web application which is going to have to handle a lot of simultaneous requests. I've setup a test environment and some jmeter scripts to do load testing and I notice I can reduce the CPU and memory footprint of my application if I make most pages Stateless.

我已将代码添加到最大页面的 onBeforeRender() 方法中,以显示哪些组件导致我的页面有状态.这是我用于检测的代码:

I've added code to the onBeforeRender() method of the biggest page to show me which of the components are causing my page to be stateful. This is the code I have for detecting that:

@Override
protected void onBeforeRender() {    
    if (!getSession().isTemporary()) {
        visitChildren(Component.class, new IVisitor<Component>() {
            @Override
            public Object component(Component component) {
                String pageClassName = AbstractStatelessBasePage.this.getClass().getName();
                if (!component.isStateless()) {

                    String msg = pageClassName+" is stateful because of stateful component " + component.getClass().getName() + " with id " + component.getId() + ".";

                    List<IBehavior> behaviourList = component.getBehaviors();
                    for (IBehavior iBehavior : behaviourList) {
                        if (!iBehavior.getStatelessHint(component)) {
                            msg += "\n\t" + "The component has stateful behaviour: " + iBehavior.getClass().getName();
                        }
                    }
                    LOG.error(msg);
                }

                checkedPages.add(pageClassName);
                return CONTINUE_TRAVERSAL;
            }
        });
    }
}

在输出中,我看到有状态行为是由页面中某些现有组件使用的 AjaxLinks 引起的:

In the output I see that the stateful behavior is caused by AjaxLinks used by some of the existing components in the pages:

ERROR - AbstractStatelessBasePage$1.component(45) | HomePage is stateful because of stateful component InfoGrid$InfoButton with id infoButton.
    The component has stateful behaviour: org.apache.wicket.ajax.markup.html.AjaxLink$1

我尝试在一些地方添加返回true"的 getStatelessHint() 方法,但它似乎没有帮助.我还检查了 AjaxLink 的 Wicket 源代码、它的超类和一些周围的代码,但我似乎无法发现为什么 AjaxLink 在所有情况下都需要有状态.

I have tried to add getStatelessHint() methods returning "true" in a few places, but it doesn's seem to help. I've also checked the Wicket source code of AjaxLink, its superclasses and some surrounding code, but I can't seem to discover why AjaxLink needs to be stateful in all cases.

在我的例子中,AjaxLink 位于无状态页面中,并且链接不存储状态.我怎样才能让 Wicket 明白这个 AjaxLink 可以是无状态的?

In my case, the AjaxLink is in an otherwise Stateless page and the link does not store state. How can I make Wicket understand that this AjaxLink can be stateless?

感谢您的帮助,罗尔夫

接受的答案适用于 Wicket 1.4.19.

在 maven pom.xml 中添加以下内容:

Added the following to the maven pom.xml:

<dependency>
    <groupId>com.jolira</groupId>
    <artifactId>wicket-stateless</artifactId>
    <version>1.0.8</version>
</dependency>

将所有扩展AjaxLink"的组件更改为扩展StatelessAjaxFallbackLink".

Changed all components which extended "AjaxLink" to extend "StatelessAjaxFallbackLink".

不要忘记将以下内容添加到您的 WicketApplication 类中,它会为您节省一些故障排除时间:

Don't forget to add the following to your WicketApplication class, it will save you some troubleshooting time:

@Override
protected IRequestCycleProcessor newRequestCycleProcessor() {
    return new StatelessWebRequestCycleProcessor();
}

请注意,出于某种原因,StatelessForm 和其他无状态的东西在转发器(如ListView")中不起作用.

Please note that StatelessForm and other stateless stuff does not work from within a repeater (like "ListView") for some reason.

推荐答案

当您向页面添加 Ajax 行为(AjaxLink 使用 AjaxEventBehavior)时,页面将变为有状态.这是因为当您单击链接时,Wicket 会尝试在服务器上查找页面实例,然后在其中查找链接组件,最后执行其回调方法 - 例如点击().不存储页面就没有办法找到ajax行为实例并执行其回调方法.

The page becomes stateful when you add an Ajax behavior to it (AjaxLink uses AjaxEventBehavior). This is because when you click a link Wicket tries to find the page instance at the server, then find the link component inside it, and finally execute its callback method - e.g. onClick(). Without storing the page there is no way how to find the ajax behavior instance and execute its callback method.

您可以使用 Jolira 的 Ajax 行为和组件 (https://github.com/jolira/wicket-stateless).它们的工作方式略有不同——当您单击 Jolira 的 AjaxLink 时,Ajax 调用会创建一个全新的页面实例,在其中找到新创建的 StatelessAjaxLink,执行其回调方法,最终使用 AjaxRequestTarget 为 Ajax 响应添加组件/javascript,然后丢弃新创建的页面实例(它被垃圾回收).下一个 Ajax 请求对一个全新的页面实例执行相同的操作.

You can use Jolira's Ajax behaviors and components (https://github.com/jolira/wicket-stateless). They work a bit differently - when you click on Jolira's AjaxLink the Ajax call creates a completely new instance of the page, finds the freshly created StatelessAjaxLink in it, executes its callback method, eventually uses AjaxRequestTarget to add components/javascript for the Ajax response and discards the newly created page instance (it is garbage collected). Next Ajax request does the same with a completely new page instance.

有人会问为什么 Jolira 的代码不在 Wicket 核心中?"- 因为它给出了部分解决方案.例如:点击 statelessAjaxLink1 创建一个新页面,在 StatelessAjaxLink 的新实例上执行 onClick(),其中 PanelA 替换为 PanelB,并将此面板(PanelB)添加到 AjaxRequestTarget.简而言之:单击此链接将替换页面中面板的主体.如果 PanelB 内部有 StatelessAjaxLink2,则无法找到此链接.为什么 ?因为点击它会创建一个新的 Page 实例,这个新实例会有 PanelA,而不是 PanelB,因此没有办法找到 StatelessAjaxLink2 来执行它的 onClick() 方法.

One would ask "Why Jolira's code is not in Wicket core ?" - because it gives partial solution. For example: clicking on statelessAjaxLink1 creates a new Page, executes onClick() on the new instance of the StatelessAjaxLink where PanelA is replaced with PanelB, and adds this panel (PanelB) to AjaxRequestTarget. In brief: clicking this link replaces the body of a panel in the page. If PanelB has a StatelessAjaxLink2 inside itself then this link is unfindable. Why ? Because clicking on it will create a new instance of the Page and this new instance will have PanelA, not PanelB, and thus there is no way to find StatelessAjaxLink2 to execute its onClick() method.

如果您的场景足够简单并且 Jolira 的组件涵盖了您的案例,那么请使用它们.请注意,更复杂的场景可能会失败.

If your scenario is simple enough and Jolira's components cover your cases then use them. Just be aware that more complex scenario may fail.

这篇关于我怎样才能让 Wicket 的“AjaxLink"无国籍?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆