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