Spring webflux

Spring 5.0 Spring webflux 是一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务。
springboot2.0发布不久,最近研究了一下springboot2.0的新特性,其中就发现了webflux。

下面是spring-flux的一个demo话不多少上代码

使用webflux和MVC的区别就是在artifacId后面加上flux

<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>2.0.0.RELEASE</version></parent><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-webflux</artifactId></dependency>
@RestControllerpublic class HelloController {    @GetMapping("/hello")    public String hello() {        return "hello world";    }}
在webflux中有Handler和Router 的概念,分别与springmvc中的controllerr和equest mapper相对应,通俗的将就是handler就是真正处理请求的bean,可以在handler中编写处理请求的逻辑,而Router就是如何让请求找到对应的handler中的方法处理,下面我们来实现一个简单的handler和router。
@Componentpublic class HelloWorldHandler {    public Mono<ServerResponse> helloWorld(ServerRequest request){        return ServerResponse.ok()                .contentType(MediaType.TEXT_PLAIN)                .body(BodyInserters.fromObject("hello flux"));    }    }
上面是一个简单的handler只相应了一个“hello flux” 字符串!
@Configurationpublic class RouterConfig {    @Autowired    private HelloWorldHandler helloWorldHandler;    @Bean    public RouterFunction<?> helloRouter() {        return RouterFunctions.route(RequestPredicates.GET("/hello"), helloWorldHandler::helloWorld);    }}
上面是对应的router对应的是匹配一个get方式的/hello请求,然后调用helloWorldHandler中的helloWorld方法向浏览器输出一个文本类型的字符串
再来一个例子
@Componentpublic 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");                return ServerResponse.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", "账号或密码错误");                    return ServerResponse.status(HttpStatus.UNAUTHORIZED)                            .contentType(MediaType.APPLICATION_JSON_UTF8)                            .body(BodyInserters.fromObject(result));                } else {                    result.put("token", "无效token");                    return ServerResponse.ok()                            .contentType(MediaType.APPLICATION_JSON_UTF8)                            .body(BodyInserters.fromObject(result));                }            });        });    }}
@Configurationpublic 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);    }}