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"); + } + +}