1

背景: liferay 5.x サーバーにデプロイされた Spring MVC フレームワークを使用してポートレットを開発しています。現在、私は 3.0.0.RELEASE を使用しています。期待どおりにすべてが正常に機能しています。つまり、 @RenderMapping(params="myaction=editFolderForm") @RenderMapping(params="myaction=editEntryForm") @RenderMapping
@ActionMapping(params="myaction=editEntry") などの注釈を使用すると、 DefaultAnnotationHandlerMapping は期待どおりに機能しますすべてのリクエストのハンドラーを見つける際に。

しかし、何らかの正当な理由により、3.0.0.RELEASE の代わりに 3.1.2.RELEASE である最新バージョンを使用する必要があります。

すべてのリクエストのハンドラーを見つける際に、 DefaultAnnotationHandlerMapping が期待どおりに機能していないことがわかりました。Springフレームワークの内部をデバッグすることで、何が問題なのかを突き止めました。これがバグかどうか誰かが教えてくれるように、明確に説明したいと思います。

AbstractMapBasedHandlerMapping である DefaultAnnotationHandlerMapping の親クラス:

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 では完全に機能しています。次の 2 つのセクションでは、ソートが重要な理由と、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 に答える