Spring WebFlux入门实践

1,752 阅读2分钟

简单介绍

spring-webflux是spring在5.0版本后提供的一套响应式编程风格的web开发框架。
这个框架包含了spring-framework和spring mvc,它可以运行在Netty、Undertow以及3.1版本以上的Serlvet容器上。
你可以在项目中同时使用spring-webmvc和spring-webflux,或者只用其中一个来开发web应用。

什么是“响应式”

所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。可见响应式是非阻塞的,意味着调用方法后,CPU可以去做别的事情,当接收到数据响应时CPU再回来处理,这种方式提高了系统的吞吐量。
而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。流式编程已不陌生了,Java8提供的stream api就是这种风格。这套标准包括对运行环境(JVM、JavaScript)以及网络协议相关的规范。

开始

0. 演示项目的目录结构

C@}G1]HN%NFEZJIHCO(81.png

1. 创建一个springboot工程并引入依赖

我用到的springboot版本为2.3.7

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

2. 编写代码

  1. Controller层将使用几种不同的风格返回结果
  2. service层则是一个耗时5秒的方法

Controller

@RestController
public class WebFluxController {

    private static final Logger log =  LoggerFactory.getLogger(WebFluxController.class);
    @Resource
    private WebFluxService webFluxService;

    /**
     * 方式一
     * @param id
     * @return
     */
    @GetMapping("/hello1")
    public Mono<String> helloWebFlux(@RequestParam("id") String id){
        log.info("webflux start..");
        Mono<String> result = Mono.fromSupplier(()-> webFluxService.helloWebFlux(id));
        log.info("webflux end..");
        return result;
    }

    /**
     * 方式二
     * @param id
     * @return
     */
    @GetMapping("/hello2")
    public Mono<String> helloWebFlux2(@RequestParam("id") String id){
        return Mono.just("hello")
                .publishOn(Schedulers.elastic())
                .map(s -> webFluxService.helloWebFlux(id));
    }

    /**
     * MVC方式
     * @param id
     * @return
     */
    @GetMapping("/hello3")
    public String helloWebFlux3(@RequestParam("id") String id){
        log.info("mvc start..");
        String result = webFluxService.helloWebFlux(id);
        log.info("mvc end..");
        return result;
    }

    /**
     * Flux : 返回0-n个元素
     * 注:需要指定MediaType
     * @return
     */
    @GetMapping(value = "/hello4", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    private Flux<String> flux() {
        Flux<String> result = Flux
                .fromStream(IntStream.range(1, 5).mapToObj(i -> {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                    }
                    return "flux data--" + i;
                }));
        return result;
    }
}

Service

public interface WebFluxService {
    String helloWebFlux(String id);
}
@Service
public class WebFluxServiceImpl implements WebFluxService {
    @Override
    public String helloWebFlux(String id) {
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
        }
        return "Hello Webflux" + id;
    }
}

对比MVC和Webflux的区别

  1. 浏览器端感受的结果都一样,都是5秒后响应。
  2. 后端日志

image.png

一个阻塞等待,一个异步等待。

  1. WebFlux支持服务器推送,如接口/hello4

Webflux的编程式请求方式

@Component
public class HiHandler {
    public Mono<ServerResponse> sayHi(ServerRequest request){
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue("Hi,this is SpringWebFlux"));
    }
}
@Configuration
public class WebFluxFunction {
    @Bean
    public RouterFunction<ServerResponse> routSayHi(HiHandler handler){
        return RouterFunctions
                .route(RequestPredicates.GET("/hi")
                        .and(RequestPredicates.accept(MediaType.ALL)),handler::sayHi);
    }
}

请求127.0.0.1:8080/hi就会返回Hi,this is SpringWebFlux;

Webflux的拦截器

实现接口WebFilter进行拦截

参考:(6条消息) 还在用Springmvc?不妨认识下Spring-webflux_yasin�的博客-CSDN博客