Skip to content

Commit 9c19469

Browse files
committed
Reinstate removal of semicolon content
Commit 5b1165 was an attempt to leave semicolon content in the URL path while ignoring it for request mapping purposes. However, it becomes quite difficult to manage and semicolon content should not always be ignored (sometimes a semicolon is used as a separator of multiple items in a path segment, rather than for matrix variables). This change effectively reverts back to the original approach in 3.2 where a flag on AbstractHandlerMapping can be used to have semicolon content removed or kept. If kept, path segments with matrix variables must be represented with a path segment. The main difference is that by default it is removed everywhere including the MVC namespace and Java config. Issue: SPR-10427, SPR-10234
1 parent 25701ef commit 9c19469

File tree

10 files changed

+34
-54
lines changed

10 files changed

+34
-54
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
156156
handlerMappingDef.getPropertyValues().add("order", 0);
157157
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
158158
String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
159+
if (element.hasAttribute("enableMatrixVariables")) {
160+
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
161+
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
162+
}
159163

160164
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
161165
RuntimeBeanReference validator = getValidator(element, source, parserContext);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public void setUrlDecode(boolean urlDecode) {
127127

128128
/**
129129
* Set if ";" (semicolon) content should be stripped from the request URI.
130-
* <p>The default value is {@code false}.
130+
* <p>The default value is {@code true}.
131131
* @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
132132
*/
133133
public void setRemoveSemicolonContent(boolean removeSemicolonContent) {

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.Map;
2727
import java.util.Set;
28+
2829
import javax.servlet.ServletException;
2930
import javax.servlet.http.HttpServletRequest;
3031

@@ -37,7 +38,6 @@
3738
import org.springframework.web.method.HandlerMethod;
3839
import org.springframework.web.method.HandlerMethodSelector;
3940
import org.springframework.web.servlet.HandlerMapping;
40-
import org.springframework.web.util.UrlPathHelper;
4141

4242
/**
4343
* Abstract base class for {@link HandlerMapping} implementations that define a
@@ -62,12 +62,6 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
6262
private final MultiValueMap<String, T> urlMap = new LinkedMultiValueMap<String, T>();
6363

6464

65-
public AbstractHandlerMethodMapping() {
66-
UrlPathHelper pathHelper = new UrlPathHelper();
67-
pathHelper.setRemoveSemicolonContent(false);
68-
setUrlPathHelper(pathHelper);
69-
}
70-
7165
/**
7266
* Whether to detect handler methods in beans in ancestor ApplicationContexts.
7367
* <p>Default is "false": Only beans in the current ApplicationContext are

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,6 @@
4242
*/
4343
public final class PatternsRequestCondition extends AbstractRequestCondition<PatternsRequestCondition> {
4444

45-
private static UrlPathHelper pathHelperNoSemicolonContent;
46-
47-
static {
48-
pathHelperNoSemicolonContent = new UrlPathHelper();
49-
pathHelperNoSemicolonContent.setRemoveSemicolonContent(true);
50-
}
51-
5245
private final Set<String> patterns;
5346

5447
private final UrlPathHelper pathHelper;
@@ -217,15 +210,10 @@ public PatternsRequestCondition getMatchingCondition(HttpServletRequest request)
217210
}
218211

219212
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
220-
String lookupPathNoSemicolonContent = (lookupPath.indexOf(';') != -1) ?
221-
pathHelperNoSemicolonContent.getLookupPathForRequest(request) : null;
222213

223214
List<String> matches = new ArrayList<String>();
224215
for (String pattern : patterns) {
225216
String match = getMatchingPattern(pattern, lookupPath);
226-
if (match == null && lookupPathNoSemicolonContent != null) {
227-
match = getMatchingPattern(pattern, lookupPathNoSemicolonContent);
228-
}
229217
if (match != null) {
230218
matches.add(match);
231219
}

spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,17 @@
231231
</xsd:appinfo>
232232
</xsd:annotation>
233233
</xsd:attribute>
234+
<xsd:attribute name="enableMatrixVariables" type="xsd:boolean">
235+
<xsd:annotation>
236+
<xsd:documentation><![CDATA[
237+
Matrix variables can appear in any path segment, each matrix variable separated with a ";" (semicolon).
238+
For example "/cars;color=red;year=2012". By default they're removed from the URL. If this property
239+
is set to true, matrix variables are not removed from the URL, and the request mapping pattern
240+
must use URI variable in path segments where matrix variables are expected. For example "/{cars}".
241+
Matrix variables can then be injected into a controller method with @MatrixVariable.
242+
]]></xsd:documentation>
243+
</xsd:annotation>
244+
</xsd:attribute>
234245
<xsd:attribute name="ignoreDefaultModelOnRedirect" type="xsd:boolean">
235246
<xsd:annotation>
236247
<xsd:documentation><![CDATA[

spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,14 @@
1616

1717
package org.springframework.web.servlet.config;
1818

19-
import static org.junit.Assert.assertEquals;
20-
import static org.junit.Assert.assertFalse;
21-
import static org.junit.Assert.assertNotNull;
22-
import static org.junit.Assert.assertNull;
23-
import static org.junit.Assert.assertSame;
24-
import static org.junit.Assert.assertTrue;
25-
2619
import java.lang.annotation.Retention;
2720
import java.lang.annotation.RetentionPolicy;
2821
import java.lang.reflect.Method;
2922
import java.util.Arrays;
3023
import java.util.Date;
3124
import java.util.List;
3225
import java.util.Locale;
26+
3327
import javax.servlet.RequestDispatcher;
3428
import javax.validation.constraints.NotNull;
3529

@@ -86,6 +80,8 @@
8680
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
8781
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
8882

83+
import static org.junit.Assert.*;
84+
8985
/**
9086
* @author Keith Donald
9187
* @author Arjen Poutsma
@@ -117,6 +113,7 @@ public void testDefaultConfig() throws Exception {
117113
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
118114
assertNotNull(mapping);
119115
assertEquals(0, mapping.getOrder());
116+
assertTrue(mapping.getUrlPathHelper().shouldRemoveSemicolonContent());
120117
mapping.setDefaultHandler(handlerMethod);
121118

122119
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.json");
@@ -182,6 +179,10 @@ public void testCustomConversionService() throws Exception {
182179
public void testCustomValidator() throws Exception {
183180
loadBeanDefinitions("mvc-config-custom-validator.xml", 12);
184181

182+
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
183+
assertNotNull(mapping);
184+
assertFalse(mapping.getUrlPathHelper().shouldRemoveSemicolonContent());
185+
185186
RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class);
186187
assertNotNull(adapter);
187188
assertEquals(true, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,15 @@
1616

1717
package org.springframework.web.servlet.mvc.condition;
1818

19-
import static org.junit.Assert.assertEquals;
20-
import static org.junit.Assert.assertNotNull;
21-
import static org.junit.Assert.assertNull;
22-
2319
import java.util.Arrays;
2420
import java.util.List;
2521

2622
import javax.servlet.http.HttpServletRequest;
2723

2824
import org.junit.Test;
2925
import org.springframework.mock.web.test.MockHttpServletRequest;
30-
import org.springframework.web.util.UrlPathHelper;
26+
27+
import static org.junit.Assert.*;
3128

3229
/**
3330
* @author Rossen Stoyanchev
@@ -186,16 +183,6 @@ public void matchPatternContainsExtension() {
186183
assertNull(match);
187184
}
188185

189-
@Test
190-
public void matchIgnorePathParams() {
191-
UrlPathHelper pathHelper = new UrlPathHelper();
192-
pathHelper.setRemoveSemicolonContent(false);
193-
PatternsRequestCondition condition = new PatternsRequestCondition(new String[] {"/foo/bar"}, pathHelper, null, true, true);
194-
PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo;q=1/bar;s=1"));
195-
196-
assertNotNull(match);
197-
}
198-
199186
@Test
200187
public void compareEqualPatterns() {
201188
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*");

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@
1616

1717
package org.springframework.web.servlet.mvc.method;
1818

19-
import static org.junit.Assert.assertArrayEquals;
20-
import static org.junit.Assert.assertEquals;
21-
import static org.junit.Assert.assertNotNull;
22-
import static org.junit.Assert.assertNull;
23-
import static org.junit.Assert.assertSame;
24-
import static org.junit.Assert.fail;
25-
2619
import java.lang.reflect.Method;
2720
import java.util.Arrays;
2821
import java.util.Collections;
@@ -61,6 +54,8 @@
6154
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
6255
import org.springframework.web.util.UrlPathHelper;
6356

57+
import static org.junit.Assert.*;
58+
6459
/**
6560
* Test fixture with {@link RequestMappingInfoHandlerMapping}.
6661
*
@@ -90,6 +85,7 @@ public void setUp() throws Exception {
9085

9186
this.handlerMapping = new TestRequestMappingInfoHandlerMapping();
9287
this.handlerMapping.registerHandler(testController);
88+
this.handlerMapping.setRemoveSemicolonContent(false);
9389
}
9490

9591
@Test

spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-custom-validator.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
xmlns:mvc="http://www.springframework.org/schema/mvc"
44
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
55
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
6-
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
6+
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
77

8-
<mvc:annotation-driven validator="validator" ignoreDefaultModelOnRedirect="true" />
8+
<mvc:annotation-driven validator="validator"
9+
ignoreDefaultModelOnRedirect="true" enableMatrixVariables="true" />
910

1011
<bean id="validator" class="org.springframework.web.servlet.config.MvcNamespaceTests$TestValidator" />
1112

src/reference/docbook/mvc.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,9 +1173,7 @@ public void findPet(
11731173
<para>Note that to enable the use of matrix variables, you must set the
11741174
<classname>removeSemicolonContent</classname> property of
11751175
<classname>RequestMappingHandlerMapping</classname> to <code>false</code>.
1176-
By default it is set to <code>true</code> with the exception of the
1177-
MVC namespace and the MVC Java config both of which automatically enable
1178-
the use of matrix variables.</para>
1176+
By default it is set to <code>false</code>.</para>
11791177

11801178
</section>
11811179

0 commit comments

Comments
 (0)