This article is a simple use of functional programming with WebFlux using SpringBoot2 and will continue to write WebFlux related articles.
I have been studying WebFlux recently, and there will be some related articles in the future.
First, take a look at a picture on Srping’s official website to compare SpringMvc with Spring WebFlux, as shown in the following figure:
In the official documentation check WebFlux: docs. Spring. IO/spring/docs… , WebFlux provides functional programming, this article briefly introduces the simple use of WebFlux functional programming.
New project
Create a project that introduces webFlux dependencies in a POM file. The complete POM file is as follows:
<? xml version="1.0" encoding="UTF-8"? > <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Dalaoyang < / groupId > < artifactId > springboot2_webflux < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < packaging > jar < / packaging > < name > springboot2_webflux < / name > <description>springboot2_webflux</description> <parent> <groupId>org.springframework.boot</groupId> < artifactId > spring - the boot - starter - parent < / artifactId > < version >. 2.0.3 RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> < project. Reporting. OutputEncoding > utf-8 < / project. Reporting. OutputEncoding > < Java version > 1.8 < / Java version > </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
First of all, try to see if SpringMvc can still be used after introducing WebFlux dependencies. Create a new HelloController, the complete code is as follows. After executing it, it is found that it can be accessed normally, which is actually what we call annotated programming.
package com.dalaoyang.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author dalaoyang * @project springboot_learn * @package com.dalaoyang.controller * @email [email protected] * @date 2018/7/30 */ @RestController public class HelloController { @GetMapping("hello")
public String Hello() {return "Hello this is SpringWebFlux"; }}Copy the code
The result is shown below:
Next, use functional programming. First check the official documentation, as shown below:
We need to create a HandlerFunction that returns Mono, create a new HiHandler, and write a method Hi inside it. The complete code is as follows:
package com.dalaoyang.handler;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
/**
* @author dalaoyang
* @project springboot_learn
* @package com.dalaoyang.handler
* @email [email protected]
* @date 2018/7/30
*/
@Component
public class HiHandler {
public Mono<ServerResponse> Hi(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject("Hi , this is SpringWebFlux")); }}Copy the code
ServerResponse is the corresponding encapsulated object. The following is its source code, which contains the response status, response, etc. The code is as follows:
package org.springframework.web.reactive.function.server;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.reactivestreams.Publisher;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public interface ServerResponse {
HttpStatus statusCode();
HttpHeaders headers();
MultiValueMap<String, ResponseCookie> cookies();
Mono<Void> writeTo(ServerWebExchange var1, ServerResponse.Context var2);
static ServerResponse.BodyBuilder from(ServerResponse other) {
return new DefaultServerResponseBuilder(other);
}
static ServerResponse.BodyBuilder status(HttpStatus status) {
return new DefaultServerResponseBuilder(status);
}
static ServerResponse.BodyBuilder status(int status) {
return new DefaultServerResponseBuilder(status);
}
static ServerResponse.BodyBuilder ok() {
return status(HttpStatus.OK);
}
static ServerResponse.BodyBuilder created(URI location) {
ServerResponse.BodyBuilder builder = status(HttpStatus.CREATED);
return (ServerResponse.BodyBuilder)builder.location(location);
}
static ServerResponse.BodyBuilder accepted() {
returnstatus(HttpStatus.ACCEPTED); } static ServerResponse.HeadersBuilder<? >noContent() {
return status(HttpStatus.NO_CONTENT);
}
static ServerResponse.BodyBuilder seeOther(URI location) {
ServerResponse.BodyBuilder builder = status(HttpStatus.SEE_OTHER);
return (ServerResponse.BodyBuilder)builder.location(location);
}
static ServerResponse.BodyBuilder temporaryRedirect(URI location) {
ServerResponse.BodyBuilder builder = status(HttpStatus.TEMPORARY_REDIRECT);
return (ServerResponse.BodyBuilder)builder.location(location);
}
static ServerResponse.BodyBuilder permanentRedirect(URI location) {
ServerResponse.BodyBuilder builder = status(HttpStatus.PERMANENT_REDIRECT);
return (ServerResponse.BodyBuilder)builder.location(location);
}
static ServerResponse.BodyBuilder badRequest() {
returnstatus(HttpStatus.BAD_REQUEST); } static ServerResponse.HeadersBuilder<? >notFound() {
return status(HttpStatus.NOT_FOUND);
}
static ServerResponse.BodyBuilder unprocessableEntity() {
returnstatus(HttpStatus.UNPROCESSABLE_ENTITY); } public interface Context { List<HttpMessageWriter<? >> messageWriters(); List<ViewResolver> viewResolvers(); } public interface BodyBuilder extends ServerResponse.HeadersBuilder<ServerResponse.BodyBuilder> { ServerResponse.BodyBuilder contentLength(long var1); ServerResponse.BodyBuilder contentType(MediaType var1); ServerResponse.BodyBuilder hint(String var1, Object var2); <T, P extends Publisher<T>> Mono<ServerResponse> body(P var1, Class<T> var2); <T, P extends Publisher<T>> Mono<ServerResponse> body(P var1, ParameterizedTypeReference<T> var2); Mono<ServerResponse> syncBody(Object var1); Mono<ServerResponse> body(BodyInserter<? ,? super ServerHttpResponse> var1); Mono<ServerResponse> render(String var1, Object... var2); Mono<ServerResponse> render(String var1, Map<String, ? > var2); } public interface HeadersBuilder<B extends ServerResponse.HeadersBuilder<B>> { B header(String var1, String... var2); B headers(Consumer<HttpHeaders> var1); B cookie(ResponseCookie var1); B cookies(Consumer<MultiValueMap<String, ResponseCookie>> var1); B allow(HttpMethod... var1); B allow(Set<HttpMethod> var1); B eTag(String var1); B lastModified(ZonedDateTime var1); B location(URI var1); B cacheControl(CacheControl var1); B varyBy(String... var1); Mono<ServerResponse> build(); Mono<ServerResponse> build(Publisher<Void> var1); Mono<ServerResponse> build(BiFunction<ServerWebExchange, ServerResponse.Context, Mono<Void>> var1); }}Copy the code
Routerfunctions. route(RequestPredicate, HandlerFunction) provides a default implementation of RouterFunctions. Create a new HiRouter with the following code:
package com.dalaoyang.router;
import com.dalaoyang.handler.HiHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* @author dalaoyang
* @project springboot_learn
* @package com.dalaoyang.router
* @email [email protected]
* @date 2018/7/30
*/
@Configuration
public class HiRouter {
@Bean
public RouterFunction<ServerResponse> routeHi(HiHandler hiHandler) {
return RouterFunctions
.route(RequestPredicates.GET("/hi") .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), hiHandler::Hi); }}Copy the code
Start the project, and you can see from the console that both mappings are printed, as shown:
In the browser to access, http://localhost:8080/hi, the results shown:
Source code download: elder Yang code cloud
Personal website: www.dalaoyang.cn