Spring webflux

Spring WebFlux is a new, non-clogged, functional Web framework Reactive to build asynchronous, non-clogged, event-driven services. Webflux was recently discovered in a recent look at the new features of springboot2.0.

Below is a demo of Spring-Flux with very little code

The difference between using WebFlux and MVC is to add Flux after artifacId

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> . < version > 2.0.0 RELEASE < / version > < / parent > < the dependency > < groupId > org. Springframework. Boot < / groupId > <artifactId>spring-boot-starter-webflux</artifactId> </dependency>Copy the code
@RestController
public class HelloController {
	@GetMapping("/hello")
	public String hello() {
		return "hello world"; }}Copy the code

In WebFlux, there are concepts of Handler and Router, which are corresponding to Controllerr and Equest mapper in SpringMVC respectively. Generally speaking, Handler is the bean that actually processes the request, and you can write the logic to process the request in Handler. The Router is how to make the request find the corresponding handler method processing, let’s implement a simple handler and Router.

@Component
public class HelloWorldHandler {

    public Mono<ServerResponse> helloWorld(ServerRequest request){
        return ServerResponse.ok()
                .contentType(MediaType.TEXT_PLAIN)
                .body(BodyInserters.fromObject("hello flux")); }}Copy the code

Above is a simple handler that only corresponds to a “Hello flux” string!

@Configuration public class RouterConfig { @Autowired private HelloWorldHandler helloWorldHandler; @Bean public RouterFunction<? >helloRouter() {
        return RouterFunctions.route(RequestPredicates.GET("/hello"), helloWorldHandler::helloWorld); }}Copy the code

The router matches a get/Hello request and then calls the helloWorld method in the helloWorldHandler to output a text string to the browser

Let’s do another example

@Component
public class UserHandler {

    @Autowired
    private ReactiveRedisConnection connection;

    public Mono<ServerResponse> getTime(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
                .body(Mono.just("Now is " + new SimpleDateFormat("HH:mm:ss").format(new Date())), String.class);
    }
    public Mono<ServerResponse> getDate(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
                .body(Mono.just("Today is " + new SimpleDateFormat("yyyy-MM-dd").format(new Date())), String.class);
    }

    public Mono<ServerResponse> sendTimePerSec(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM)
                .body(Flux.interval(Duration.ofSeconds(1)).map(l -> new SimpleDateFormat("HH:mm:ss").format(new Date())), String.class);
    }


    public Mono<ServerResponse> register(ServerRequest request) {
        Mono<Map> body = request.bodyToMono(Map.class);
        return body.flatMap(map -> {
            String username = (String) map.get("username");
            String password = (String) map.get("password");
            String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
            return connection.stringCommands()
                    .set(ByteBuffer.wrap(username.getBytes()), ByteBuffer.wrap(hashedPassword.getBytes()));
        }).flatMap(aBoolean -> {
            Map<String, String> result = new HashMap<>();
            ServerResponse serverResponse = null;
            if (aBoolean){
                result.put("message"."successful");
                return ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .body(BodyInserters.fromObject(result));
            }else {
                result.put("message"."failed");
                returnServerResponse.status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(request)); }}); } public Mono<ServerResponse> login(ServerRequest request) { Mono<Map> body = request.bodyToMono(Map.class);return body.flatMap(map -> {
            String username = (String) map.get("username");
            String password = (String) map.get("password");
            return connection.stringCommands().get(ByteBuffer.wrap(username.getBytes())).flatMap(byteBuffer -> {
                byte[] bytes = new byte[byteBuffer.remaining()];
                byteBuffer.get(bytes, 0, bytes.length);
                String hashedPassword = null;
                try {
                    hashedPassword = new String(bytes, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                Map<String, String> result = new HashMap<>();
                if(hashedPassword == null || ! BCrypt.checkpw(password, hashedPassword)) { result.put("message"."Wrong account or password");
                    return ServerResponse.status(HttpStatus.UNAUTHORIZED)
                            .contentType(MediaType.APPLICATION_JSON_UTF8)
                            .body(BodyInserters.fromObject(result));
                } else {
                    result.put("token"."Invalid token");
                    returnServerResponse.ok() .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(result)); }}); }); }}Copy the code
@Configuration public class RouterConfig { @Autowired private HelloWorldHandler helloWorldHandler; @Bean public RouterFunction<? >helloRouter() {
        return RouterFunctions.route(RequestPredicates.GET("/hello"), helloWorldHandler::helloWorld);
    }

    @Autowired
    private UserHandler userHandler;

    @Bean
    public RouterFunction<ServerResponse> timerRouter() {
        return RouterFunctions.route(RequestPredicates.GET("/time"), userHandler::getTime)
                .andRoute(RequestPredicates.GET("/date"), userHandler::getDate); } @Bean public RouterFunction<? >routerFunction() {
        return RouterFunctions.route(RequestPredicates.GET("/hello"), helloWorldHandler::helloWorld)
                .andRoute(RequestPredicates.POST("/register"), userHandler::register)
                .andRoute(RequestPredicates.POST("/login"), userHandler::login)
                .andRoute(RequestPredicates.GET("/times"), userHandler::sendTimePerSec); }}Copy the code