[英]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.