[TOC]
Nowadays, reactive programming becomes more and more popular. Spring 5 and Spring Boot 2.0 also bring built-in reactive programming support.
According to the definition in Wikipedia.
Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. This means that it becomes possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease via the employed programming language(s)
Reactor is a Reactive Streams implementation, and provide fully non-blocking reactive programming model with back-pressure capability.
In this post, we will create a simple Spring Boot application with the newest Reactive APIs provided in spring-webflux
, and use Reactor-Netty as runtime instead of traditional Servlet based container.
Make sure you have already installed the following software.
- Oracle Java 8
- Apache Maven
- Gradle
- Your favorite IDE, including :
- NetBeans IDE
- Eclipse IDE (or Eclipse based IDE, Spring ToolSuite is highly recommended)
- Intellij IDEA
To kick start a Spring Boot application quickly, the simplest approach is utilizing Spring Initializer to generate the project template.
Open your favoriate browser, and go to Spring Initializer page.
Fill the form field as you need.
- You can select Maven or Gradle as build tools.
- And select Kotlin, Groovy, Java 8 as programming language.
- Then choose the Spring Boot version, be care about this field, only Spring Boot 2.0 support Reactive features, you can select the latest 2.0 milestone 4 or snapshot.
- In the group and artifact, input your desired values. Here we use the default value for demonstration purpose.
- In the Selected Dependencies field, type reactive in the input box, in the autocomplete dropdown menus, choose Reactive Web, you can also add other features as you need.
Then hint Generate Project button or use ALT+ENTER keyboard shortcuts to get the generated codes. It will popup a download dialog for you, save it into your local disk.
Extract the download files, let's try to import the codes into the popular IDEs, you can use your favorite one, including NetBeans IDE, Eclipse, Intellij IDEA etc, all of them have excellent Maven support.
NetBeans IDE can recognize Maven project automatically.
- Start up NetBeans IDE.
- Click Open project icon from toolbar or choose Open Project from File menu.
- In the Open Project dialog, find and select source codes folder, it should be marked as Mavenzied NetBeans project.
- When it is selected, click the Open Project button.
Eclipse Java EE bundle or Spring ToolSuite is highly recommended for building a Spring application.
- Starts up Eclipse.
- Select Import... from File menu.
- In the Import... dialog, select Maven/Existing Maven Project, click Next button.
- In the Import Maven Projects... dialog, click Browse button to choose the location of the source codes as Root Directory.
- Select the projects to be imported in the Projects list, then click Finish button.
For Java developers, IntelliJ IDEA is the most productive IDEs, it includes a free and open source community version and a commercial version, both have good Java and Maven support.
- Starts up IDEA.
- Select New / Project from Existing Sources... from File menu.
- Choose the source folder in the Select the File or Directory to import dialog.
- Then follow the steps in the wizard to import the codes.
Let's have a look at the project structure.
| .gitignore
| mvnw
| mvnw.cmd
| pom.xml
|
+---.mvn
| \---wrapper
| maven-wrapper.jar
| maven-wrapper.properties
|
\---src
+---main
| +---java
| | \---com
| | \---example
| | \---demo
| | DemoApplication.java
| |
| \---resources
| application.properties
|
\---test
\---java
\---com
\---example
\---demo
DemoApplicationTests.java
It is a standard Maven project, but includes optional Maven Wrapper files.
src/main/java/com/example/demo/DemoApplication.java
is the boostrap class of this application.
src/main/resources/application.properties
is the application configuration file. Spring Boot also support YAML
format.
src/test/java/com/example/demo/DemoApplicationTests.java
is a JUnit test class for this application.
Open the pom.xml
file.
There is spring-boot-stater-webflux
, like the traditional spring-boot-stater-web
, the new starter will add spring-webflux
support in this project, and enable webflux
configuration for this application .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
By default, it will use reactor-netty
as runtime.
Similar with traditional Controller
, spring-webfux
also support the same annotation when you declare controllers, but it can use the new reactive APIs.
@RestController
@RequestMapping
class MessageController {
@GetMapping
Flux<Message> allMessages(){
return Flux.just(
Message.builder().body("hello Spring 5").build(),
Message.builder().body("hello Spring Boot 2").build()
);
}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Message {
String body;
}
We just created a very simple Controller which includes a simple method to return all messages. Note here we return Flux<Message>
instead of List<Message>
.
Run the application via IDE run button, or execute mvn spring-boot:run
in your command line tool.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.M4)
...
2017-10-01 21:30:13.856 INFO 14460 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2017-10-01 21:30:13.857 INFO 14460 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2017-10-01 21:30:13.889 INFO 14460 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 7.001 seconds (JVM running for 28.193)
You can use curl
to taste the APIs.
# curl http://localhost:8080
[{"body":"hello Spring 5"},{"body":"hello Spring Boot 2"}]
It works well.
Another features provided in spring-webflux
is its functional RouterFunction
instead of traditional Controller. For those developers who prefer Lambda, this is a better option.
The above MessageController
can be replaced with the following RouterFunction
bean:
@Bean
public RouterFunction<ServerResponse> routes() {
return route(GET("/"),
(req)-> ok()
.body(
BodyInserters.fromObject(
Arrays.asList(Message.builder().body("hello Spring 5").build(),
Message.builder().body("hello Spring Boot 2").build()
)
)
)
);
}
These codes are equivalent with the former controller in functionality.
Check out the source codes from my github account.