diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index 36c7a74702..34636e1b9f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -180,6 +180,7 @@ public class MvcUriComponentsBuilder { builder.path(prefix); String mapping = getClassMapping(controllerType); + mapping = (!StringUtils.hasText(prefix + mapping) ? "/" : mapping); builder.path(mapping); return builder; @@ -280,10 +281,10 @@ public class MvcUriComponentsBuilder { * @RequestMapping("/people/{id}/addresses") * class AddressController { * - * @RequestMapping("/{country}") + * @GetMapping("/{country}") * public HttpEntity<Void> getAddressesForCountry(@PathVariable String country) { ... } * - * @RequestMapping(value="/", method=RequestMethod.POST) + * @PostMapping * public void addAddress(Address address) { ... } * } * @@ -546,6 +547,9 @@ public class MvcUriComponentsBuilder { if (StringUtils.hasLength(path) && !path.startsWith("/")) { path = "/" + path; } + else if (!StringUtils.hasText(prefix + path)) { + path = "/"; + } builder.path(path); return applyContributors(builder, method, args); @@ -577,11 +581,11 @@ public class MvcUriComponentsBuilder { Assert.notNull(controllerType, "'controllerType' must not be null"); RequestMapping mapping = AnnotatedElementUtils.findMergedAnnotation(controllerType, RequestMapping.class); if (mapping == null) { - return "/"; + return ""; } String[] paths = mapping.path(); if (ObjectUtils.isEmpty(paths) || !StringUtils.hasLength(paths[0])) { - return "/"; + return ""; } if (paths.length > 1 && logger.isTraceEnabled()) { logger.trace("Using first of multiple paths on " + controllerType.getName()); @@ -597,7 +601,7 @@ public class MvcUriComponentsBuilder { } String[] paths = requestMapping.path(); if (ObjectUtils.isEmpty(paths) || !StringUtils.hasLength(paths[0])) { - return "/"; + return ""; } if (paths.length > 1 && logger.isTraceEnabled()) { logger.trace("Using first of multiple paths on " + method.toGenericString()); @@ -845,7 +849,7 @@ public class MvcUriComponentsBuilder { public MethodArgumentBuilder(@Nullable UriComponentsBuilder baseUrl, Class controllerType, Method method) { Assert.notNull(controllerType, "'controllerType' is required"); Assert.notNull(method, "'method' is required"); - this.baseUrl = baseUrl != null ? baseUrl : UriComponentsBuilder.fromPath(getPath()); + this.baseUrl = (baseUrl != null ? baseUrl : UriComponentsBuilder.fromPath(getPath())); this.controllerType = controllerType; this.method = method; this.argumentValues = new Object[method.getParameterCount()]; @@ -854,7 +858,7 @@ public class MvcUriComponentsBuilder { private static String getPath() { UriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentServletMapping(); String path = builder.build().getPath(); - return path != null ? path : ""; + return (path != null ? path : ""); } public MethodArgumentBuilder arg(int index, Object value) { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java index 182504eeed..f772da13ab 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java @@ -234,12 +234,19 @@ public class MvcUriComponentsBuilderTests { } @Test - public void fromMethodNameNotMapped() { - UriComponents uriComponents = fromMethodName(UnmappedController.class, "unmappedMethod").build(); + public void fromMethodNameInUnmappedController() { + UriComponents uriComponents = fromMethodName(UnmappedController.class, "requestMappingMethod").build(); assertThat(uriComponents.toUriString()).isEqualTo("http://localhost/"); } + @Test // gh-29897 + public void fromMethodNameInUnmappedControllerMethod() { + UriComponents uriComponents = fromMethodName(UnmappedControllerMethod.class, "getMethod").build(); + + assertThat(uriComponents.toUriString()).isEqualTo("http://localhost/path"); + } + @Test public void fromMethodNameWithCustomBaseUrlViaStaticCall() { UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("https://example.org:9090/base"); @@ -535,7 +542,16 @@ public class MvcUriComponentsBuilderTests { private class UnmappedController { @RequestMapping - public void unmappedMethod() { + public void requestMappingMethod() { + } + } + + + @RequestMapping("/path") + private class UnmappedControllerMethod { + + @GetMapping + public void getMethod() { } }