背景: 我正在使用部署在liferay 5.x服務器中的Spring MVC框架開發Portlet。 目前我正在使用3.0.0.RELEASE。一切工作正常,如預期。 也就是說,當我使用註釋等 @RenderMapping(PARAMS = 「myaction = editFolderForm」) @RenderMapping(PARAMS = 「myaction = editEntryForm」) @RenderMapping
@ActionMapping(PARAMS = 「myaction = editEntry」) DefaultAnnotationHandlerMapping按照預期爲每個請求查找處理程序。這是Spring 3.1.2(特別是Spring Portlet MVC)中的一個Bug嗎?
但是,出於某種正當理由,我必須使用更多的最新版本,它是3.1.2.RELEASE而不是3.0.0.RELEASE。
我發現DefaultAnnotationHandlerMapping不像預期的那樣爲每個請求找到一個處理程序。我通過調試Spring框架的內部知道了什麼是問題。 我想解釋清楚,以便有人可以告訴我,如果這是一個錯誤。
在父類DefaultAnnotationHandlerMapping的這AbstractMapBasedHandlerMapping:
package org.springframework.web.portlet.handler;
public abstract class AbstractMapBasedHandlerMapping<K> extends AbstractHandlerMapping {
....
....
/**
* Determines a handler for the computed lookup key for the given request.
* @see #getLookupKey
*/
@Override
@SuppressWarnings("unchecked")
protected Object getHandlerInternal(PortletRequest request) throws Exception {
...
if (handler instanceof Map) {
Map<PortletRequestMappingPredicate, Object> predicateMap =
(Map<PortletRequestMappingPredicate, Object>) handler;
List<PortletRequestMappingPredicate> predicates =
new LinkedList<PortletRequestMappingPredicate>(predicateMap.keySet());
LINE 81: Collections.sort(predicates); ///////////////// PROBLEM
for (PortletRequestMappingPredicate predicate : predicates) {
if (predicate.match(request)) {
predicate.validate(request);
return predicateMap.get(predicate);
}
}
return null;
}
return handler;
}
....
....
}
此排序是在Spring 3.1.2搞砸了,並在Spring 3.0.0工作得很好。 在接下來的兩節中,我將告訴你爲什麼排序很重要,以及它如何在Spring 3.1.2中搞砸。
爲什麼排序很重要?
此HandlerMapping按節點搜索排序後的鏈接列表,直到它找到與特定處理程序匹配爲止。在我的代碼的基礎上,我有多個控制器,它的方法被映射與以下注釋等
@RenderMapping --->默認
@RenderMapping(PARAMS = 「myaction = editEntryController」)
@RenderMapping( PARAMS = 「myaction = editFolderController」)
等
的Collections.sort()取決於的compareTo(..)每個XXXPredicate類的方法。
當一個請求到達時,應該檢查myaction參數是否等於「editEntryController」,「editFolderController」,以及最後如果沒有任何匹配,那麼只有使用@RenderMapping註釋註釋的默認控制器應該匹配。
使用Spring 3.0.0,其工作方式與預期完全相同。 因爲Spring 3.2.1,它的行爲不像那樣。
對於這兩個版本,在排序之前,列表是相同的。
myaction=editEntry,
myaction=editEntryForm,
org.springframework.web.portlet.mvc.anno[email protected]123bea8a,
myaction=REDIRECT_TO_DEFAULT_PAGE,
, ---------------------------------> This empty string corrsponds to the default @RenderMapping
myaction=selectFolderEntries,
myaction=searchResults,
myaction=addEntry,
myaction=addEntryForm,
myaction=showMyEntries,
myaction=showRecentEntries,
org.springframework.web.portlet.mvc.anno[email protected]4f1e9e2d,
myaction=editFolder,
myaction=editFolderForm,
myaction=addFolder,
myaction=addFolderForm
排序後,
使用Spring 3.0。0,
org.springframework.web.portlet.mvc.anno[email protected]123bea8a,
org.springframework.web.portlet.mvc.anno[email protected]4f1e9e2d,
myaction=editEntry,
myaction=editEntryForm,
myaction=REDIRECT_TO_DEFAULT_PAGE,
myaction=selectFolderEntries,
myaction=searchResults,
myaction=addEntry,
myaction=addEntryForm,
myaction=showMyEntries,
myaction=showRecentEntries,
myaction=editFolder,
myaction=editFolderForm,
myaction=addFolder,
myaction=addFolderForm,
---------------> Default mapping i.e. @RenderMapping
藉助於Spring 3.1.2(忽略之類的東西[]),
[myaction=editEntry]
[myaction=editEntryForm]
deleteFolder
[myaction=REDIRECT_TO_DEFAULT_PAGE]
[] --------------------------> this is wrongly placed in middle.
[myaction=selectFolderEntries]
[myaction=searchResults]
[myaction=addEntry]
[myaction=addEntryForm]
[myaction=showMyEntries]
[myaction=showRecentEntries]
deleteEntry
[myaction=editFolder]
[myaction=editFolderForm]
[myaction=addFolder]
[myaction=addFolderForm]
null
這是一個鏈表。並且從第一個節點檢查每個映射。 如果在列表中間找到默認[]即空映射,則返回true,就好像這是正確的處理程序,其餘處理程序未被檢查。
那麼這是Spring框架3.2.1中的一個bug嗎?