Skip to content

Commit e74b332

Browse files
committed
fixed regression: method-level patterns without type-level pattern do not need to start with a slash (SPR-6598)
1 parent b54a099 commit e74b332

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,11 @@ public Method resolveHandlerMethod(HttpServletRequest request) throws ServletExc
487487
boolean match = false;
488488
if (mappingInfo.paths.length > 0) {
489489
List<String> matchedPaths = new ArrayList<String>(mappingInfo.paths.length);
490-
for (String methodLevelPattern : mappingInfo.paths) {
491-
String matchedPattern = getMatchedPattern(methodLevelPattern, lookupPath, request);
490+
for (String mappedPattern : mappingInfo.paths) {
491+
if (!hasTypeLevelMapping() && !mappedPattern.startsWith("/")) {
492+
mappedPattern = "/" + mappedPattern;
493+
}
494+
String matchedPattern = getMatchedPattern(mappedPattern, lookupPath, request);
492495
if (matchedPattern != null) {
493496
if (mappingInfo.matches(request)) {
494497
match = true;

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,11 @@ else if (AnnotationUtils.findAnnotation(handlerType, Controller.class) != null)
154154
/**
155155
* Derive URL mappings from the handler's method-level mappings.
156156
* @param handlerType the handler type to introspect
157-
* @param indicateEmpty whether the returned array should contain
158-
* <code>null</code> in case of an empty {@link RequestMapping} value.
157+
* @param hasTypeLevelMapping whether the method-level mappings are nested
158+
* within a type-level mapping
159159
* @return the array of mapped URLs
160160
*/
161-
protected String[] determineUrlsForHandlerMethods(Class<?> handlerType, final boolean indicateEmpty) {
161+
protected String[] determineUrlsForHandlerMethods(Class<?> handlerType, final boolean hasTypeLevelMapping) {
162162
String[] subclassResult = determineUrlsForHandlerMethods(handlerType);
163163
if (subclassResult != null) {
164164
return subclassResult;
@@ -175,10 +175,13 @@ public void doWith(Method method) {
175175
String[] mappedPatterns = mapping.value();
176176
if (mappedPatterns.length > 0) {
177177
for (String mappedPattern : mappedPatterns) {
178+
if (!hasTypeLevelMapping && !mappedPattern.startsWith("/")) {
179+
mappedPattern = "/" + mappedPattern;
180+
}
178181
addUrlsForPath(urls, mappedPattern);
179182
}
180183
}
181-
else if (indicateEmpty) {
184+
else if (hasTypeLevelMapping) {
182185
// empty method-level RequestMapping
183186
urls.add(null);
184187
}

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,32 @@ public void relativePathDispatchingController() throws Exception {
964964
assertEquals("mySurpriseView", response.getContentAsString());
965965
}
966966

967+
@Test
968+
public void relativeMethodPathDispatchingController() throws Exception {
969+
initServlet(MyRelativeMethodPathDispatchingController.class);
970+
servlet.init(new MockServletConfig());
971+
972+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
973+
MockHttpServletResponse response = new MockHttpServletResponse();
974+
servlet.service(request, response);
975+
assertEquals("myView", response.getContentAsString());
976+
977+
request = new MockHttpServletRequest("GET", "/yourApp/myOther");
978+
response = new MockHttpServletResponse();
979+
servlet.service(request, response);
980+
assertEquals("myOtherView", response.getContentAsString());
981+
982+
request = new MockHttpServletRequest("GET", "/hisApp/myLang");
983+
response = new MockHttpServletResponse();
984+
servlet.service(request, response);
985+
assertEquals("myLangView", response.getContentAsString());
986+
987+
request = new MockHttpServletRequest("GET", "/herApp/surprise.do");
988+
response = new MockHttpServletResponse();
989+
servlet.service(request, response);
990+
assertEquals("mySurpriseView", response.getContentAsString());
991+
}
992+
967993
@Test
968994
public void nullCommandController() throws Exception {
969995
initServlet(MyNullCommandController.class);
@@ -1360,8 +1386,8 @@ public void trailingSlash() throws Exception {
13601386
}
13611387

13621388
/*
1363-
* Controllers
1364-
*/
1389+
* Controllers
1390+
*/
13651391

13661392
@RequestMapping("/myPath.do")
13671393
private static class MyController extends AbstractController {
@@ -1836,6 +1862,30 @@ public void mySurpriseHandle(HttpServletResponse response) throws IOException {
18361862
}
18371863
}
18381864

1865+
@Controller
1866+
private static class MyRelativeMethodPathDispatchingController {
1867+
1868+
@RequestMapping("**/myHandle")
1869+
public void myHandle(HttpServletResponse response) throws IOException {
1870+
response.getWriter().write("myView");
1871+
}
1872+
1873+
@RequestMapping("/**/*Other")
1874+
public void myOtherHandle(HttpServletResponse response) throws IOException {
1875+
response.getWriter().write("myOtherView");
1876+
}
1877+
1878+
@RequestMapping("**/myLang")
1879+
public void myLangHandle(HttpServletResponse response) throws IOException {
1880+
response.getWriter().write("myLangView");
1881+
}
1882+
1883+
@RequestMapping("/**/surprise")
1884+
public void mySurpriseHandle(HttpServletResponse response) throws IOException {
1885+
response.getWriter().write("mySurpriseView");
1886+
}
1887+
}
1888+
18391889
@Controller
18401890
private static class MyNullCommandController {
18411891

0 commit comments

Comments
 (0)