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也会提醒你的

相关推荐
weixin_438335402 分钟前
Spring Boot实现接口时间戳鉴权
java·spring boot·后端
寻月隐君7 分钟前
探索Web3新速度:Sonic高性能Layer-1上的BlindAuction智能合约实践
后端·web3·github
pan_junbiao34 分钟前
Spring框架的设计模式
java·spring·设计模式
天天摸鱼的java工程师44 分钟前
Redis 集群缓存不一致?这篇把坑给你挖明白了
后端
天天摸鱼的java工程师1 小时前
Redis 除了做缓存还能干什么?
后端
AntBlack1 小时前
Trae Agent :能提高开发效率的功能都值亲自体验一下
后端·ai编程·trae
江梦寻2 小时前
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
开发语言·后端·python·macos·架构·策略模式
风象南2 小时前
SpringBoot的4种死信队列处理方式
java·spring boot·后端
互联网全栈架构3 小时前
遨游Spring AI:第一盘菜Hello World
java·人工智能·后端·spring
coderSong25689 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket