일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- kafkastream
- scala 2.10
- Logstash
- gradle
- Kafka
- enablekafkastreams
- Elk
- Spring
- RabbitMQ
- statestore
- play framework
- scala
- avo
- spring-batch
- kafka interactive query
- schema registry
- spring-kafka
- kafkastreams
- 카프카
- aws
- Slick
- coursera
- spring-cloud-stream
- springboot
- Elasticsearch
- kafka streams
- 한빛미디어
- reactive
- confluent
- 플레이 프레임워크
- Today
- Total
b
springframework 5.0 webflux module 본문
오늘 날자 기준으로 SpringFramework는 v5.0.0.M5 (링크) 가 나와있고, RC1 버전이 5월 예정되어 있지만 힘들지싶다 (링크) Spring 5에는 webflux 모듈이 새로 추가되었지만, 사실 Spring5 마일스톤에서 착실히 진행 중이던 spring-web-reactive가 이름이 바뀐 모듈이다. (JIRA)
0. webflux 모듈은 webmvc를 대체하는 가?
우선 spring-mvc 모듈은 여전히 남아 있다. 기존에서 @RestController 을 사용하던 방식을 여전히 사용 할 수 있다. (즉 webflux따위 몰라도 된다)
그리고 새로운 방법으로도 사용 할 수 있다. 링크 에서 말하는 것처럼 webflux 모듈은 완전히 새로운 방법 (Java8 람다를 이용한 라우팅/핸들링)과 @Controller와 handling을 사용하는 중간 적인 방법도 사용 가능하다.
요즘들어서 통합테스트의 어려움, 몇년간 Scala에서 느끼던 재미를 Java에서는 느끼지 못해 아쉬웠는데, webflux가 좀 해소해주지 않을까 해서 살펴볼 예정이다.
1. 프로젝트의 생성
Intellij2017.1 버전은 New Project 할때 SpringBoot 2.0.0-SNAPSHOT을 지원한다. 그러므로 쉽게 프로젝트를 생성 할 수 있다. 아니라면 링크 의 pom.xml, Application.java를 참고한다.
2. Hello Controller 만들기
기존의 mvc모듈이 @RestController, @RequestMapping으로 이루어져 있다면, webflux는 RouterFunction, HandlerFunctions 2개 인터페이스를 알 면 된다. 그리고 HttpServletRequest,HttpServletResponse는 잊고, ServerRequest, ServerResponse를 기억 하면 된다.
가장 기본적인 ‘hello world’를 반환하는 /hello를 만들어보도록 하자.
public class HelloRouter { RouterFunctionrouter() { return route(RequestPredicates.path("/hello"), helloHandler()); } HandlerFunction helloHandler() { return request -> ServerResponse.ok().body(fromObject("Hello World")); } }
작성하고 Application.java를 springboot로 실행해고 http://localhost:8080/hello 를 호출해도 404 NotFound 이다. 왜일까?
문서 상으로 Running Server (링크)가 있지만 좀 귀찮은 방식이라 좀 더 찾아보니 링크 처럼 spring-boot-starter-webflux는 RouterFunction beans에 대해서 자동으로 디텍팅을 해준다고 한다.
그래서 class HelloRouter 위에 @Configuration 와, router() 메소드 위에 @Bean을 붙여준 후 다시 http://localhost:8080/hello 를 실행해본다면 ‘Hello World’ 메세지를 확인 할 수 있을 것이다.
@Configuration public class HelloRouter { @Bean RouterFunction처럼 좀 더 괜찮은 방식으로 써도 괜찮다.router() { return route(RequestPredicates.path("/hello"), request -> ServerResponse.ok() .body(fromObject(new Date()))); } }
3. 여러개의 Router ( Controller ) 만들기
@Bean RouterFunctionrouter() { return route(GET("/hello"), request -> ServerResponse.ok().body(fromObject("Hello-World"))) .andRoute(GET("/time"), request -> ServerResponse.ok().body(fromObject(new Date()))) .andRoute(DELETE("/delete"), request -> { System.out.println("delete"); return ServerResponse.ok().body(Mono.empty());}); }
처럼 andRoute를 이용해서 체이닝을 할 수도 있고 많은 static method를 이용해서 URI Mapping도 좀 더 짧게 코딩 할 수 있다. 아래 처럼 메소드 래퍼런스를 이용하여 좀 더 깔끔하게 정리할 수도 있다.
public class HelloHandler { public MonohelloWorld(ServerRequest request){ return ok().body(fromObject("Hello-World")); } public Mono time(ServerRequest request){ return ok().body(fromObject(new Date())); } public Mono printlog(ServerRequest request){ System.out.println("delete"); return ServerResponse.ok().body(Mono.empty()); } } @Configuration public class HelloRouter { HelloHandler helloHandler = new HelloHandler(); @Bean RouterFunction router() { return route(GET("/hello"), helloHandler::helloWorld) .andRoute(GET("/time"), helloHandler::time) .andRoute(DELETE("/delete"), helloHandler::printlog); } }
4. Request에서 Parameter 받아오기
public Monospringboot가 스타트업 될때 로깅메시지를 보면 ReactiveWebServerApplicationContext와 함께 /hello 매핑 정보가 없다는 것도 볼 수 있다.getName(ServerRequest request){ String name = request.pathVariable("name"); return ok().body(fromObject(name)); } //curl -H "Content-Type: application/json" -X POST -d '{"id":"id","name":"name"}' http://localhost:8080/param/body public Mono getBody(ServerRequest request){ Mono notFound = ServerResponse.notFound().build(); Mono user = request.bodyToMono(User.class); return user.flatMap(u -> ok().body(u).switchIfEmpty(notFound)); }
2017-04-22 21:07:59.915 INFO 1806 --- [ main] .r.c.ReactiveWebServerApplicationContext : Refreshing org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext@1dd92fe2: startup date [Sat Apr 22 21:07:59 KST 2017]; root of context hierarchy 2017-04-22 21:08:00.701 WARN 1806 --- [ main] o.h.v.m.ParameterMessageInterpolator : HV000184: ParameterMessageInterpolator has been chosen, EL interpolation will not be supported 2017-04-22 21:08:00.909 INFO 1806 --- [ main] o.s.w.r.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler] 2017-04-22 21:08:00.910 INFO 1806 --- [ main] o.s.w.r.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
'spring framework' 카테고리의 다른 글
SPRINGBOOT로 AWS LAMBDA 이용하기 (0) | 2017.07.07 |
---|---|
springboot 2.0의 RouterFunction 스캐닝 방법 (0) | 2017.04.25 |
VTD-XML 을 이용한 XML 분리. (0) | 2014.02.14 |
스프링MVC에서 return type이 String 일경우. (4) | 2013.11.29 |
angularjs , $resource 와 spring @requestBody (0) | 2013.11.11 |