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 按预期工作为每个请求找到一个处理程序。

但是,出于某种正当理由,我必须使用更新的最新版本,即 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() 取决于每个 XXXPredicate 类的 compareTo(..) 方法。

当请求首先出现时,应检查 myaction 参数是否等于“editEntryController”、“editFolderController”……最后如果没有匹配项,则仅应匹配带有 @RenderMapping 注释的默认控制器。

在 Spring 3.0.0 中,它的工作方式与预期完全一样。至于 Spring 3.2.1,它的行为不是那样的。

对于这两个版本,在排序之前,列表是相同的。

myaction=editEntry, 
myaction=editEntryForm, 
org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping$ResourceMappingPredicate@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.annotation.DefaultAnnotationHandlerMapping$ResourceMappingPredicate@4f1e9e2d, 
 myaction=editFolder, 
 myaction=editFolderForm,
 myaction=addFolder, 
 myaction=addFolderForm

排序后,

使用 Spring 3.0.0,

org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping$ResourceMappingPredicate@123bea8a, 
org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping$ResourceMappingPredicate@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 中的错误吗?

4

1 回答 1

1

我有同样的问题。只有版本 3.1.4 对我有用。

于 2015-01-28T22:29:23.803 回答