WebFlux初尝试

前言

WebFluxSpring5.0推出的基于Reactor响应式模型的MVC框架,目前在国内相关的使用和资料比较少,本栏目主要分享一些使用过程中的经验,帮助大家入门并熟练使用这种响应式模型的编程方式。

开始

JDK我使用的是17,大家也可以升级下自己远古版本1.8了

引入依赖

xml 复制代码
 
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.3</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>annotationProcessor</scope>
    </dependency>
</dependencies>

最简单的依赖就能启动项目

Hello World 环节

和Spring MVC并没有太大的差异,返回值用Mono Wrap一下

java 复制代码
@RestController
public class TestController {

    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("hello world");
    }

}

Run

启动项目 , 打印这条日志恭喜成功

Netty started on port 8080

shell 复制代码
curl http://127.0.0.1:8080/hello

hello world

Why

SpringApplication.run(Application.class, args)创造世界

java 复制代码
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
            // 看这里,从classpath推导出springboot web环境
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}
java 复制代码
   private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

	private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

	private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

	static WebApplicationType deduceFromClasspath() {
        // 在这判断,如果是reactive环境就会启动响应式的容器
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

Mono与Flux

响应式中一个数据也能看为信号 Mono.just("hello world")可以看为发了一个信号,而Flux则是用来发送多个信号,比如Flux.just("1", "2", "3"),初学者可以简单粗暴的理解为List类型。

通常来说响应式是需要我们进行消费的,不然一切都是白搭,比如

java 复制代码
Mono.just("hello world")
.subscribe(s -> System.out.println(s));

但是Demo中我们并没有消费,因为webflux框架已经帮我们消费了

我们在自己写定时任务之类的操作中一定记得主动消费!!!

java 复制代码
@Scheduled(fixedRateString = "5000")
public void scheduled() {
    Mono.just("hello world")
            .subscribe();
}

这只是简单的示例,实际中很可能是处理数据库数据、Redis数据等任务。

重要,前面的不看这个必须看!

Reactor模型是调度少量的线程来处理更多的任务,和我们以往的性能到底瓶颈就增加线程池的操作很不一样,所有在响应式的世界里禁止阻塞,这非常重要将严重影响你系统的吞吐量。

以前阻塞式编程的做法是,100个工人每个工人负责一个事情,忙不过来了就加到200个人。

响应式的处理是,只分配10个工人,每个工人通过一个总的调度来处理多个事情,比如1个人工人有10袋水泥,现在只需要把1袋搬上车就可以忙其他事情,等车运完这袋水泥回来再搬1袋,阻塞就相当于这个工人只能在这守着直到10袋水泥都搬运完。

所以求求你们千万不要在代码里.block();除非你单独开一个线程池来处理。

Idea也会提醒你的

相关推荐
海绵波波1073 小时前
flask后端开发(10):问答平台项目结构搭建
后端·python·flask
网络风云4 小时前
【魅力golang】之-反射
开发语言·后端·golang
Q_19284999064 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
陈无左耳、5 小时前
Spring Boot应用开发实战:从入门到精通
spring boot
烟波人长安吖~5 小时前
【目标跟踪+人流计数+人流热图(Web界面)】基于YOLOV11+Vue+SpringBoot+Flask+MySQL
vue.js·pytorch·spring boot·深度学习·yolo·目标跟踪
运维&陈同学5 小时前
【Kibana01】企业级日志分析系统ELK之Kibana的安装与介绍
运维·后端·elk·elasticsearch·云原生·自动化·kibana·日志收集
小天努力学java6 小时前
【面试系列】深入浅出 Spring
java·spring·面试
Javatutouhouduan8 小时前
如何系统全面地自学Java语言?
java·后端·程序员·编程·架构师·自学·java八股文
后端转全栈_小伵8 小时前
MySQL外键类型与应用场景总结:优缺点一目了然
数据库·后端·sql·mysql·学习方法
编码浪子9 小时前
Springboot高并发乐观锁
后端·restful