簡體   English   中英

如何讓Wicket的“AjaxLink”無狀態?

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

我正在構建一個Wicket Web應用程序,它將不得不處理大量的同時請求。 我已經設置了一個測試環境和一些jmeter腳本來進行負載測試,我注意到如果我使大多數頁面無狀態,我可以減少應用程序的CPU和內存占用。

我已經在最大頁面的onBeforeRender()方法中添加了代碼,以向我展示哪些組件導致我的頁面有狀態。 這是我檢測到的代碼:

@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;
            }
        });
    }
}

在輸出中,我看到有狀態行為是由頁面中某些現有組件使用的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

我試圖添加getStatelessHint()方法在一些地方返回“true”,但它似乎沒有幫助。 我還檢查了AjaxLink的Wicket源代碼,它的超類和一些周圍的代碼,但我似乎無法發現為什么AjaxLink在所有情況下都需要有狀態。

就我而言,AjaxLink處於無狀態頁面,鏈接不存儲狀態。 如何讓Wicket明白這個AjaxLink可以是無狀態的?

謝謝你的幫助,羅爾夫

編輯:接受的答案適用於Wicket 1.4.19。

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

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

更改了擴展“AjaxLink”以擴展“StatelessAjaxFallbackLink”的所有組件。

不要忘記將以下內容添加到WicketApplication類中,它將為您節省一些故障排除時間:

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

請注意,由於某種原因,StatelessForm和其他無狀態內容在轉發器(如“ListView”)中不起作用。

當您向其添加Ajax行為時,該頁面將變為有狀態(AjaxLink使用AjaxEventBehavior)。 這是因為當您單擊鏈接時,Wicket會嘗試在服務器上查找頁面實例,然后在其中找到鏈接組件,最后執行其回調方法 - 例如onClick()。 如果不存儲頁面,就無法找到ajax行為實例並執行其回調方法。

您可以使用Jolira的Ajax行為和組件(https://github.com/jolira/wicket-stateless)。 它們的工作方式略有不同 - 當您單擊Jolira的AjaxLink時,Ajax調用會創建一個全新的頁面實例,在其中找到新創建的StatelessAjaxLink,執行其回調方法,最終使用AjaxRequestTarget為Ajax響應添加組件/ javascript,丟棄新創建的頁面實例(它是垃圾回收)。 下一個Ajax請求對一個全新的頁面實例也是如此。

有人會問“為什么Jolira的代碼不在Wicket核心?” - 因為它提供了部分解決方案。 例如:單擊statelessAjaxLink1創建一個新頁面,在其中PanelA替換為PanelB的StatelessAjaxLink的新實例上執行onClick(),並將此面板(PanelB)添加到AjaxRequestTarget。 簡而言之:單擊此鏈接將替換頁面中面板的主體。 如果PanelB內部有StatelessAjaxLink2,則此鏈接不可用。 為什么? 因為單擊它將創建一個新的Page實例,這個新實例將具有PanelA,而不是PanelB,因此無法找到StatelessAjaxLink2來執行其onClick()方法。

如果您的場景足夠簡單並且Jolira的組件涵蓋了您的案例,那么請使用它們。 請注意,更復雜的情況可能會失敗。

wicket wiki上引用了無狀態AjaxFallbackLink代碼,以及一個相關的github項目,您可以從那里獲得以下鏈接。 不確定這會完全解決你的問題,但它至少可能是有益的。

Wicket 6也嘗試過類似的方法,但作者警告說它是實驗性的。 代碼在這里 我沒有嘗試使用它,因此無法保證它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM