简体   繁体   English

如何让Wicket的“AjaxLink”无状态?

[英]How can I make Wicket's “AjaxLink” Stateless?

I am building a Wicket web application which is going to have to handle a lot of simultaneous requests. 我正在构建一个Wicket Web应用程序,它将不得不处理大量的同时请求。 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. 我已经设置了一个测试环境和一些jmeter脚本来进行负载测试,我注意到如果我使大多数页面无状态,我可以减少应用程序的CPU和内存占用。

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. 我已经在最大页面的onBeforeRender()方法中添加了代码,以向我展示哪些组件导致我的页面有状态。 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;
            }
        });
    }
}

In the output I see that the stateful behavior is caused by AjaxLinks used by some of the existing components in the pages: 在输出中,我看到有状态行为是由页面中某些现有组件使用的AjaxLink引起的:

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

I have tried to add getStatelessHint() methods returning "true" in a few places, but it doesn's seem to help. 我试图添加getStatelessHint()方法在一些地方返回“true”,但它似乎没有帮助。 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. 就我而言,AjaxLink处于无状态页面,链接不存储状态。 How can I make Wicket understand that this AjaxLink can be stateless? 如何让Wicket明白这个AjaxLink可以是无状态的?

Thanks for your help, Rolf 谢谢你的帮助,罗尔夫

Edit: Accepted answer works with Wicket 1.4.19. 编辑:接受的答案适用于Wicket 1.4.19。

Added the following to the maven pom.xml: 在maven pom.xml中添加了以下内容:

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

Changed all components which extended "AjaxLink" to extend "StatelessAjaxFallbackLink". 更改了扩展“AjaxLink”以扩展“StatelessAjaxFallbackLink”的所有组件。

Don't forget to add the following to your WicketApplication class, it will save you some troubleshooting time: 不要忘记将以下内容添加到WicketApplication类中,它将为您节省一些故障排除时间:

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

Please note that StatelessForm and other stateless stuff does not work from within a repeater (like "ListView") for some reason. 请注意,由于某种原因,StatelessForm和其他无状态内容在转发器(如“ListView”)中不起作用。

The page becomes stateful when you add an Ajax behavior to it (AjaxLink uses AjaxEventBehavior). 当您向其添加Ajax行为时,该页面将变为有状态(AjaxLink使用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 - eg onClick(). 这是因为当您单击链接时,Wicket会尝试在服务器上查找页面实例,然后在其中找到链接组件,最后执行其回调方法 - 例如onClick()。 Without storing the page there is no way how to find the ajax behavior instance and execute its callback method. 如果不存储页面,就无法找到ajax行为实例并执行其回调方法。

You can use Jolira's Ajax behaviors and components (https://github.com/jolira/wicket-stateless). 您可以使用Jolira的Ajax行为和组件(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). 它们的工作方式略有不同 - 当您单击Jolira的AjaxLink时,Ajax调用会创建一个全新的页面实例,在其中找到新创建的StatelessAjaxLink,执行其回调方法,最终使用AjaxRequestTarget为Ajax响应添加组件/ javascript,丢弃新创建的页面实例(它是垃圾回收)。 Next Ajax request does the same with a completely new page instance. 下一个Ajax请求对一个全新的页面实例也是如此。

One would ask "Why Jolira's code is not in Wicket core ?" 有人会问“为什么Jolira的代码不在Wicket核心?” - 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. 例如:单击statelessAjaxLink1创建一个新页面,在其中PanelA替换为PanelB的StatelessAjaxLink的新实例上执行onClick(),并将此面板(PanelB)添加到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. 如果PanelB内部有StatelessAjaxLink2,则此链接不可用。 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. 因为单击它将创建一个新的Page实例,这个新实例将具有PanelA,而不是PanelB,因此无法找到StatelessAjaxLink2来执行其onClick()方法。

If your scenario is simple enough and Jolira's components cover your cases then use them. 如果您的场景足够简单并且Jolira的组件涵盖了您的案例,那么请使用它们。 Just be aware that more complex scenario may fail. 请注意,更复杂的情况可能会失败。

There is code for a stateless AjaxFallbackLink referenced on the wicket wiki , and a related github project that you can get to following links from there. wicket wiki上引用了无状态AjaxFallbackLink代码,以及一个相关的github项目,您可以从那里获得以下链接。 Not sure this will completely solve your problem, but it may at least be instructive. 不确定这会完全解决你的问题,但它至少可能是有益的。

A similar approach has been tried for wicket 6, but the author warns it's experimental. Wicket 6也尝试过类似的方法,但作者警告说它是实验性的。 The code is here . 代码在这里 I haven't tried to use it and thus can't vouch for it. 我没有尝试使用它,因此无法保证它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM