Browse Source

Use LinkedHashmap to preserve insert order

In several places in the spring-webmvc module, URL patterns / objects
relationships are kept in `HashMap`s. When matching with actual URLs,
the algorithm uses a pattern comparator to sort the matching patterns
and select the most specific. But the underlying collection
implementation does not keep the original order which can lead to
inconsistencies.

This commit changes the underlying collection implementation to
`LinkedHashmap`s, in order to keep the insert order if the comparator
does not reorder entries.

Issue: SPR-13798
pull/940/head
Brian Clozel 10 years ago
parent
commit
3be35c053d
  1. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java
  2. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java
  3. 19
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java

4
spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java

@ -16,7 +16,7 @@
package org.springframework.web.servlet.handler; package org.springframework.web.servlet.handler;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -55,7 +55,7 @@ import org.springframework.util.CollectionUtils;
*/ */
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
private final Map<String, Object> urlMap = new HashMap<String, Object>(); private final Map<String, Object> urlMap = new LinkedHashMap<String, Object>();
/** /**

4
spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java

@ -19,7 +19,7 @@ package org.springframework.web.servlet.resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -55,7 +55,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
private PathMatcher pathMatcher = new AntPathMatcher(); private PathMatcher pathMatcher = new AntPathMatcher();
private final Map<String, ResourceHttpRequestHandler> handlerMap = new HashMap<String, ResourceHttpRequestHandler>(); private final Map<String, ResourceHttpRequestHandler> handlerMap = new LinkedHashMap<String, ResourceHttpRequestHandler>();
private boolean autodetect = true; private boolean autodetect = true;

19
spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java

@ -19,9 +19,10 @@ package org.springframework.web.servlet.resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
@ -60,7 +61,7 @@ public class VersionResourceResolver extends AbstractResourceResolver {
private AntPathMatcher pathMatcher = new AntPathMatcher(); private AntPathMatcher pathMatcher = new AntPathMatcher();
/** Map from path pattern -> VersionStrategy */ /** Map from path pattern -> VersionStrategy */
private final Map<String, VersionStrategy> versionStrategyMap = new HashMap<String, VersionStrategy>(); private final Map<String, VersionStrategy> versionStrategyMap = new LinkedHashMap<String, VersionStrategy>();
/** /**
@ -209,17 +210,17 @@ public class VersionResourceResolver extends AbstractResourceResolver {
*/ */
protected VersionStrategy getStrategyForPath(String requestPath) { protected VersionStrategy getStrategyForPath(String requestPath) {
String path = "/".concat(requestPath); String path = "/".concat(requestPath);
List<String> matchingPatterns = new ArrayList<String>(); List<String> matchingPatterns = new ArrayList<String>();
for (String pattern : this.versionStrategyMap.keySet()) { for (String pattern : this.versionStrategyMap.keySet()) {
if (this.pathMatcher.match(pattern, path)) { if (this.pathMatcher.match(pattern, path)) {
matchingPatterns.add(pattern); matchingPatterns.add(pattern);
} }
} }
if (!matchingPatterns.isEmpty()) { if (!matchingPatterns.isEmpty()) {
Comparator<String> comparator = this.pathMatcher.getPatternComparator(path); Comparator<String> comparator = this.pathMatcher.getPatternComparator(path);
Collections.sort(matchingPatterns, comparator); Collections.sort(matchingPatterns, comparator);
return this.versionStrategyMap.get(matchingPatterns.get(0)); return this.versionStrategyMap.get(matchingPatterns.get(0));
} }
return null; return null;
} }

Loading…
Cancel
Save