Python 官方文档:入门教程 => 点击学习
目录1. 前言2. spring-WEBflux简介3. 什么是“响应式”4. Spring-webflux的响应式api5. Spring mvc 还是 W
Spring 提供了两个并行堆栈。一种是基于带有 Spring MVC 和 Spring Data 结构的 Servlet API。另一个是完全反应式堆栈,它利用了 Spring WebFlux 和 Spring Data 的反应式存储库。在这两种情况下,Spring Security 都提供了对两种堆栈的支持。
反应式宣言
Spring WebFlux 是在 5.0 版中添加的。它是完全无阻塞的,支持 Reactive Streams
背压,并且可以在 Netty、Undertow 和 Servlet 3.1+ 容器等服务器上运行。
Spring-webflux官网
所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。可见响应式是非阻塞的,意味着调用方法后,CPU可以去做别的事情,当接收到数据响应时CPU再回来处理,这种方式提高了系统的吞吐量。
而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。流式编程已不陌生了,Java8提供的stream api就是这种风格。这套标准包括对运行环境(JVM、javascript)以及网络协议相关的规范。
和传统的阻塞式servlet容器不一样。响应式容器能进一步提高资源的利用率,避免线程长时间处于等待状态,能以较少的线程处理更多的请求,缺点是整个处理链路必须是异步的,是基于事件响应的,不能阻塞事件线程,不然服务器性能会急剧下降,当然spring webflux
并不能完整的替代传统的阻塞式容器,可根据需求进行选型。
应用案例:Geteway
所有微服务的请求都会通过网关,如果采用mvc 对于并发量有一定的瓶颈。
Spring-webflux
框架是基于Reactor
这个开源项目开发的。Reactor
框架是跟Spring
紧密配合的。
里边提供了两种API类型,分别是Mono
和Flux
;
Mono
表示0 或 1个元素,Flux
表示0 至 N个元素,这两个web框架分别代表着两种不同类型的编程流派,官方给出了一个图作为对比如下
建议考虑以下具体点:
其次: webflux兼容大部分springMVC的注解,也可以像mvc那样创建controller处理请求。
区别:
尽管webmvc
和webflux
都支持使用注解来定义一个Controller
,但是其实现方式完全不同。
webmvc是一个Servlet应用,实现是阻塞式IO,其维护一个线程池来处理每一个用户请求,也就是当Servlet
容器启动时,就会创建比如10个线程出来,因此系统吞吐量的瓶颈在于有限的连接数和阻塞的请求处理过程。
webflux可以基于netty
这样的NIO网络框架,它只需要很少的几个工作线程(Event loop worker)就能够处理并响应请求。由于无需阻塞等待方法返回,CPU资源就得到了更好的利用。
webflux并不能让程序运行地更快;而是提高了并发处理请求的能力,即提高系统吞吐量。
pom依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.5.9</version>
</dependency>
</dependencies>
定义对象:
public class Person {
private Integer id;
private Integer age;
private String name;
public Person(Integer id, Integer age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public Person() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
然后定义PersonController
,响应式风格中不再使用@RequestMapping
声明地址映射,而是通过RouterFunctions.route().GET()
方法:
@Configuration
public class PersonRouter {
@Resource
private PersonHandler personHandler;
@Bean
public RouterFunction<ServerResponse> personRoutes() {
return RouterFunctions.route()
.GET("/person/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), personHandler::getPerson)
.GET("/person", RequestPredicates.accept(MediaType.APPLICATION_jsON), personHandler::listPeople)
.POST("/person", personHandler::createPerson)
.build();
}
}
在PersonHandler
中处理对应的Http请求,等同于MVC架构中的Service层
@Component
public class PersonHandler {
@Resource
private IPersonDao personDao;
public Mono<ServerResponse> listPeople(ServerRequest request) {
Flux<Person> people = personDao.getList();
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(people, Person.class);
}
public Mono<ServerResponse> createPerson(ServerRequest request) {
return request.bodyToMono(Person.class)
.flatMap(i -> personDao.savePerson(i))
.flatMap(p -> ServerResponse.ok().bodyValue(p));
}
public Mono<ServerResponse> getPerson(ServerRequest request) {
int personId = Integer.parseInt(request.pathVariable("id"));
return personDao.getPerson(personId)
.flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(person))
.switchIfEmpty(ServerResponse.notFound().build());
}
}
IPersonDao
public interface IPersonDao {
Flux<Person> getList();
Mono<Void> savePerson(Person person);
Mono<Person> getPerson(Integer id);
}
PersonDao
@Component
public class PersonDao implements IPersonDao {
private final List<Person> personList = new ArrayList<>();
public PersonDao() {
this.personList.add(new Person(1, 17, "张三"));
this.personList.add(new Person(2, 18, "李四"));
}
@Override
public Flux<Person> getList() {
return Flux.fromIterable(personList);
}
@Override
public Mono<Void> savePerson(Person person) {
personList.add(person);
System.out.println("personList.size = " + personList);
return Mono.empty();
}
@Override
public Mono<Person> getPerson(Integer id) {
return Mono.justOrEmpty(personList.stream().filter(p -> p.getId().equals(id)).findFirst());
}
}
@SpringBootApplication
@EnableWebFlux
public class SpringWebfluxSessionApplication implements WebFluxConfigurer {
public static void main(String[] args) {
SpringApplication.run(SpringWebfluxSessionApplication.class, args);
}
}
通过启动日志可以证实Spring-webflux
是默认使用Netty
提供HTTP服务
GET请求:http://127.0.0.1:8080/person
POST请求:http://127.0.0.1:8080/person
boyd:
{
"id": 9,
"age": 17,
"name": "张三"
}
控制台输出:
GET请求:http://127.0.0.1:8080/person/9
完整代码已上传 gitee Spring整合常用组件
到此这篇关于Spring-webflux 响应式编程的文章就介绍到这了,更多相关Spring webflux 响应式编程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Spring-webflux 响应式编程的实例详解
本文链接: https://www.lsjlt.com/news/166851.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0