2012-08-16 91 views
1

背景: 我正在使用部署在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嗎?

回答

1

我有同樣的問題。只有版本3.1.4爲我工作。