Это ошибка в версии 3.1.2 (в частности, в Spring Portlet MVC)?
Фон:
Я занимаюсь разработкой портлета с использованием среды Spring MVC, развернутой на сервере liferay 5.x.
В настоящее время я использую 3.0.0.RELEASE. Все работает нормально, как и ожидалось.
То есть, когда я использую аннотации, такие как
@RenderMapping (PARAMS = & Quot; MyAction = editFolderForm & Quot;)
@RenderMapping (PARAMS = & Quot; MyAction = editEntryForm & Quot;)
@RenderMapping
@ActionMapping (PARAMS = & Quot; MyAction = editEntry & Quot;)
и т.п.
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.
why sorting matters ?
Это HandlerMapping ищет отсортированный связанный список узлов по узлам, пока не найдет соответствие для определенного обработчика. В моей базе кода, у меня есть несколько контроллеров, чьи методы отображаются с такими аннотациями, как
@RenderMapping --- & gt; дефолт
@RenderMapping (PARAMS = & Quot; MyAction = editEntryController & Quot;)
@RenderMapping (PARAMS = & Quot; MyAction = editFolderController & Quot;)
и т.п.
Collections.sort () зависит от метода compareTo (..) каждого класса XXXPredicate.
когда запрос приходит первым, он должен быть проверен, если параметр myaction равен & quot; editEntryController & quot ;, & quot; editFolderController & quot ;, ... и, наконец, если ничего не совпадает, то должен соответствовать только контроллер по умолчанию, аннотированный аннотацией @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
После сортировки
С весны 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 Framework 3.2.1?