diff --git a/spring-5/pom.xml b/spring-5/pom.xml
index 605dbe39e1..4b373923ef 100644
--- a/spring-5/pom.xml
+++ b/spring-5/pom.xml
@@ -177,6 +177,7 @@
1.0.0-M4
5.0.0-M4
2.20
+ 5.0.0.RC2
diff --git a/spring-5/src/main/java/com/baeldung/Spring5Application.java b/spring-5/src/main/java/com/baeldung/Spring5Application.java
index 41b5c1eed1..aaff1797ff 100644
--- a/spring-5/src/main/java/com/baeldung/Spring5Application.java
+++ b/spring-5/src/main/java/com/baeldung/Spring5Application.java
@@ -2,8 +2,10 @@ package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
+@ComponentScan(basePackages = {"com.baeldung.web"})
public class Spring5Application {
public static void main(String[] args) {
diff --git a/spring-5/src/main/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctions.java b/spring-5/src/main/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctions.java
new file mode 100644
index 0000000000..b7436c5ba7
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctions.java
@@ -0,0 +1,61 @@
+package com.baeldung.functional;
+
+import static org.springframework.web.reactive.function.BodyInserters.fromObject;
+import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
+import static org.springframework.web.reactive.function.server.RouterFunctions.route;
+import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
+import static org.springframework.web.reactive.function.server.ServerResponse.ok;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
+import org.springframework.boot.web.server.WebServer;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.server.reactive.HttpHandler;
+import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import org.springframework.web.server.WebHandler;
+import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
+
+public class ExploreSpring5URLPatternUsingRouterFunctions {
+
+ private RouterFunction routingFunction() {
+
+ return route(GET("/p?ths"), serverRequest -> ok().body(fromObject("/p?ths"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromObject(serverRequest.pathVariable("id"))))
+ .andRoute(GET("/*card"), serverRequest -> ok().body(fromObject("/*card path was accessed")))
+ .andRoute(GET("/{var1}_{var2}"), serverRequest -> ok().body(fromObject(serverRequest.pathVariable("var1") + " , " + serverRequest.pathVariable("var2"))))
+ .andRoute(GET("/{baeldung:[a-z]+}"), serverRequest -> ok().body(fromObject("/{baeldung:[a-z]+} was accessed and baeldung=" + serverRequest.pathVariable("baeldung"))))
+ .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/")));
+ }
+
+ WebServer start() throws Exception {
+ WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction());
+ HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler)
+ .prependFilter(new IndexRewriteFilter())
+ .build();
+
+ Tomcat tomcat = new Tomcat();
+ tomcat.setHostname("localhost");
+ tomcat.setPort(9090);
+ Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
+ ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler);
+ Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet);
+ rootContext.addServletMappingDecoded("/", "httpHandlerServlet");
+
+ TomcatWebServer server = new TomcatWebServer(tomcat);
+ server.start();
+ return server;
+
+ }
+
+ public static void main(String[] args) {
+ try {
+ new FunctionalWebApplication().start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java b/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java
index 258a23a2bf..8a808fc83a 100644
--- a/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java
+++ b/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java
@@ -15,6 +15,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
+import org.springframework.web.server.WebHandler;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import reactor.core.publisher.Flux;
@@ -58,7 +59,7 @@ public class FunctionalSpringBootApplication {
@Bean
public ServletRegistrationBean servletRegistrationBean() throws Exception {
HttpHandler httpHandler = WebHttpHandlerBuilder
- .webHandler(toHttpHandler(routingFunction()))
+ .webHandler((WebHandler) toHttpHandler(routingFunction()))
.prependFilter(new IndexRewriteFilter())
.build();
ServletRegistrationBean registrationBean = new ServletRegistrationBean<>(new RootServlet(httpHandler), "/");
diff --git a/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java
index 573813b166..29f9ea43da 100644
--- a/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java
+++ b/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java
@@ -50,7 +50,7 @@ public class FunctionalWebApplication {
}
WebServer start() throws Exception {
- WebHandler webHandler = toHttpHandler(routingFunction());
+ WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction());
HttpHandler httpHandler = WebHttpHandlerBuilder
.webHandler(webHandler)
.prependFilter(new IndexRewriteFilter())
diff --git a/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java b/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java
index 3e19f81943..d218bba581 100644
--- a/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java
+++ b/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java
@@ -19,7 +19,7 @@ class IndexRewriteFilter implements WebFilter {
.mutate()
.request(builder -> builder
.method(request.getMethod())
- .contextPath(request.getContextPath())
+ .contextPath(request.getPath().toString())
.path("/test"))
.build());
}
diff --git a/spring-5/src/main/java/com/baeldung/functional/RootServlet.java b/spring-5/src/main/java/com/baeldung/functional/RootServlet.java
index 54892c829f..922809e563 100644
--- a/spring-5/src/main/java/com/baeldung/functional/RootServlet.java
+++ b/spring-5/src/main/java/com/baeldung/functional/RootServlet.java
@@ -23,12 +23,13 @@ import static org.springframework.web.reactive.function.server.RequestPredicates
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
+import org.springframework.web.server.WebHandler;
public class RootServlet extends ServletHttpHandlerAdapter {
public RootServlet() {
this(WebHttpHandlerBuilder
- .webHandler(toHttpHandler(routingFunction()))
+ .webHandler((WebHandler) toHttpHandler(routingFunction()))
.prependFilter(new IndexRewriteFilter())
.build());
}
diff --git a/spring-5/src/main/java/com/baeldung/web/PathPatternController.java b/spring-5/src/main/java/com/baeldung/web/PathPatternController.java
new file mode 100644
index 0000000000..15b689257a
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/web/PathPatternController.java
@@ -0,0 +1,40 @@
+package com.baeldung.web;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class PathPatternController {
+
+ @GetMapping("/spring5/{*id}")
+ public String URIVariableHandler(@PathVariable String id) {
+ return id;
+ }
+
+ @GetMapping("/s?ring5")
+ public String wildcardTakingExactlyOneChar() {
+ return "/s?ring5";
+ }
+
+ @GetMapping("/spring5/*id")
+ public String wildcardTakingZeroOrMoreChar() {
+ return "/spring5/*id";
+ }
+
+ @GetMapping("/resources/**")
+ public String wildcardTakingZeroOrMorePathSegments() {
+ return "/resources/**";
+ }
+
+ @GetMapping("/{baeldung:[a-z]+}")
+ public String regexInPathVariable(@PathVariable String baeldung) {
+ return baeldung;
+ }
+
+ @GetMapping("/{var1}_{var2}")
+ public String multiplePathVariablesInSameSegment(@PathVariable String var1, @PathVariable String var2) {
+ return "Two variables are var1=" + var1 + " and var2=" + var2;
+ }
+}
diff --git a/spring-5/src/main/resources/files/test/test.txt b/spring-5/src/main/resources/files/test/test.txt
new file mode 100644
index 0000000000..30d74d2584
--- /dev/null
+++ b/spring-5/src/main/resources/files/test/test.txt
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/spring-5/src/test/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctionsTest.java b/spring-5/src/test/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctionsTest.java
new file mode 100644
index 0000000000..7a38fa697f
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/functional/ExploreSpring5URLPatternUsingRouterFunctionsTest.java
@@ -0,0 +1,110 @@
+package com.baeldung.functional;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.boot.web.server.WebServer;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+public class ExploreSpring5URLPatternUsingRouterFunctionsTest {
+
+ private static WebTestClient client;
+ private static WebServer server;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ server = new ExploreSpring5URLPatternUsingRouterFunctions().start();
+ client = WebTestClient.bindToServer()
+ .baseUrl("http://localhost:" + server.getPort())
+ .build();
+ }
+
+ @AfterClass
+ public static void destroy() {
+ server.stop();
+ }
+
+ @Test
+ public void givenRouter_whenGetPathWithSingleCharWildcard_thenGotPathPattern() throws Exception {
+ client.get()
+ .uri("/paths")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("/p?ths");
+ }
+
+ @Test
+ public void givenRouter_whenMultipleURIVariablePattern_thenGotPathVariable() throws Exception {
+ client.get()
+ .uri("/test/ab/cd")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("/ab/cd");
+ }
+
+ @Test
+ public void givenRouter_whenGetMultipleCharWildcard_thenGotPathPattern() throws Exception {
+
+ client.get()
+ .uri("/wildcard")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("/*card path was accessed");
+ }
+
+ @Test
+ public void givenRouter_whenGetMultiplePathVaribleInSameSegment_thenGotPathVariables() throws Exception {
+
+ client.get()
+ .uri("/baeldung_tutorial")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("baeldung , tutorial");
+ }
+
+ @Test
+ public void givenRouter_whenGetRegexInPathVarible_thenGotPathVariable() throws Exception {
+
+ client.get()
+ .uri("/abcd")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("/{baeldung:[a-z]+} was accessed and baeldung=abcd");
+
+ client.get()
+ .uri("/1234")
+ .exchange()
+ .expectStatus()
+ .is4xxClientError();
+ }
+
+ @Test
+ public void givenResources_whenAccess_thenGot() throws Exception {
+ client.get()
+ .uri("/files/test/test.txt")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("test");
+
+ client.get()
+ .uri("/files/hello.txt")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .isEqualTo("hello");
+ }
+
+}
diff --git a/spring-5/src/test/java/com/baeldung/web/PathPatternsUsingHandlerMethodTest.java b/spring-5/src/test/java/com/baeldung/web/PathPatternsUsingHandlerMethodTest.java
new file mode 100644
index 0000000000..bb02d21c2b
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/web/PathPatternsUsingHandlerMethodTest.java
@@ -0,0 +1,102 @@
+package com.baeldung.web;
+
+import com.baeldung.web.PathPatternController;
+import com.baeldung.Spring5Application;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Spring5Application.class)
+public class PathPatternsUsingHandlerMethodTest {
+
+ private static WebTestClient client;
+
+ @BeforeClass
+ public static void setUp() {
+ client = WebTestClient.bindToController(new PathPatternController())
+ .build();
+ }
+
+ @Test
+ public void givenHandlerMethod_whenMultipleURIVariablePattern_then200() {
+
+ client.get()
+ .uri("/spring5/ab/cd")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("/ab/cd");
+ }
+
+ @Test
+ public void givenHandlerMethod_whenURLWithWildcardTakingZeroOrMoreChar_then200() {
+
+ client.get()
+ .uri("/spring5/userid")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("/spring5/*id");
+ }
+
+ @Test
+ public void givenHandlerMethod_whenURLWithWildcardTakingExactlyOneChar_then200() {
+
+ client.get()
+ .uri("/string5")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("/s?ring5");
+ }
+
+ @Test
+ public void givenHandlerMethod_whenURLWithWildcardTakingZeroOrMorePathSegments_then200() {
+
+ client.get()
+ .uri("/resources/baeldung")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("/resources/**");
+ }
+
+ @Test
+ public void givenHandlerMethod_whenURLWithRegexInPathVariable_thenExpectedOutput() {
+
+ client.get()
+ .uri("/abc")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("abc");
+
+ client.get()
+ .uri("/123")
+ .exchange()
+ .expectStatus()
+ .is4xxClientError();
+ }
+
+ @Test
+ public void givenHandlerMethod_whenURLWithMultiplePathVariablesInSameSegment_then200() {
+
+ client.get()
+ .uri("/baeldung_tutorial")
+ .exchange()
+ .expectStatus()
+ .is2xxSuccessful()
+ .expectBody()
+ .equals("Two variables are var1=baeldung and var2=tutorial");
+ }
+
+}