springwebflux 页面_Spring WebFlux 入门
1. WebFlux介绍
Spring WebFlux 是 Spring Framework 5.0中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。
Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。
(PS:所谓异步非阻塞是针对服务端而言的,是说服务端可以充分利用CPU资源去做更多事情,这与客户端无关,客户端该怎么请求还是怎么请求。)
Reactive Streams是一套用于构建高吞吐量、低延迟应用的规范。而Reactor项目是基于这套规范的实现,它是一个完全非阻塞的基础,且支持背压。Spring WebFlux基于Reactor实现了完全异步非阻塞的一套web框架,是一套响应式堆栈。
【spring-webmvc + Servlet + Tomcat】命令式的、同步阻塞的
【spring-webflux + Reactor + Netty】响应式的、异步非阻塞的
2. Spring WebFlux Framework
Spring WebFlux有两种风格:功能性和基于注释的。基于注释的与Spring MVC非常相近。例如:
1 @RestController
2 @RequestMapping("/users")
3 public class MyRestController {
4
5 @GetMapping("/{user}")
6 public Mono getUser(@PathVariable Long user) {
7 // ...
8 }
9
10 @GetMapping("/{user}/customers")
11 public Flux getUserCustomers(@PathVariable Long user) {
12 // ...
13 }
14
15 @DeleteMapping("/{user}")
16 public Mono deleteUser(@PathVariable Long user) {
17 // ...
18 }
19 }
与之等价,也可以这样写:
1 @Configuration
2 public class RoutingConfiguration {
3 @Bean
4 public RouterFunction monoRouterFunction(UserHandler userHandler) {
5 return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
6 .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
7 .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
8 }
9 }
10
11 @Component
12 public class UserHandler {
13 public Mono getUser(ServerRequest request) {
14 // ...
15 }
16 public Mono getUserCustomers(ServerRequest request) {
17 // ...
18 }
19 public Mono deleteUser(ServerRequest request) {
20 // ...
21 }
22 }
如果你同时添加了spring-boot-starter-web和spring-boot-starter-webflux依赖,那么Spring Boot会自动配置Spring MVC,而不是WebFlux。你当然可以强制指定应用类型,通过SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)
3. Hello WebFlux
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 4.0.0
5
6 org.springframework.boot
7 spring-boot-starter-parent
8 2.2.5.RELEASE
9
10
11 com.cjs.example
12 cjs-reactive-rest-service
13 0.0.1-SNAPSHOT
14 cjs-reactive-rest-service
15
16
17 1.8
18
19
20
21
22 org.springframework.boot
23 spring-boot-starter-webflux
24
25
26
27 org.springframework.boot
28 spring-boot-starter-test
29 test
30
31
32 org.junit.vintage
33 junit-vintage-engine
34
35
36
37
38 io.projectreactor
39 reactor-test
40 test
41
42
43
44
45
46
47 org.springframework.boot
48 spring-boot-maven-plugin
49
50
51
52
53
GreetingHandler.java
1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.http.MediaType;
4 import org.springframework.stereotype.Component;
5 import org.springframework.web.reactive.function.BodyInserters;
6 import org.springframework.web.reactive.function.server.ServerRequest;
7 import org.springframework.web.reactive.function.server.ServerResponse;
8 import reactor.core.publisher.Mono;
9
10 import java.util.concurrent.atomic.AtomicLong;
11
12 /**
13 * @author ChengJianSheng
14 * @date 2020-03-25
15 */
16 @Component
17 public class GreetingHandler {
18
19 private final AtomicLong counter = new AtomicLong();
20
21 /**
22 * A handler to handle the request and create a response
23 */
24 public Mono hello(ServerRequest request) {
25 return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
26 .body(BodyInserters.fromValue("Hello, Spring!"));
27
28 }
29 }
GreetingRouter.java
1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.context.annotation.Bean;
4 import org.springframework.context.annotation.Configuration;
5 import org.springframework.http.MediaType;
6 import org.springframework.web.reactive.function.server.*;
7
8 /**
9 * @author ChengJianSheng
10 * @date 2020-03-25
11 */
12 @Configuration
13 public class GreetingRouter {
14
15 /**
16 * The router listens for traffic on the /hello path and returns the value provided by our reactive handler class.
17 */
18 @Bean
19 public RouterFunction route(GreetingHandler greetingHandler) {
20 return RouterFunctions.route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), greetingHandler::hello);
21 }
22 }
GreetingWebClient.java
1 package com.cjs.example.restservice.hello;
2
3 import org.springframework.http.MediaType;
4 import org.springframework.web.reactive.function.client.ClientResponse;
5 import org.springframework.web.reactive.function.client.WebClient;
6 import reactor.core.publisher.Mono;
7
8 /**
9 * @author ChengJianSheng
10 * @date 2020-03-25
11 */
12 public class GreetingWebClient {
13
14 /**
15 * For reactive applications, Spring offers the WebClient class, which is non-blocking.
16 *
17 * WebClient can be used to communicate with non-reactive, blocking services, too.
18 */
19 private WebClient client = WebClient.create("http://localhost:8080");
20
21 private Mono result = client.get()
22 .uri("/hello")
23 .accept(MediaType.TEXT_PLAIN)
24 .exchange();
25
26 public String getResult() {
27 return ">> result = " + result.flatMap(res -> res.bodyToMono(String.class)).block();
28 }
29 }
Application.java
1 package com.cjs.example.restservice;
2
3 import com.cjs.example.restservice.hello.GreetingWebClient;
4 import org.springframework.boot.SpringApplication;
5 import org.springframework.boot.autoconfigure.SpringBootApplication;
6
7 /**
8 * @author ChengJianSheng
9 * @date 2020-03-25
10 */
11 @SpringBootApplication
12 public class CjsReactiveRestServiceApplication {
13
14 public static void main(String[] args) {
15 SpringApplication.run(CjsReactiveRestServiceApplication.class, args);
16
17 GreetingWebClient gwc = new GreetingWebClient();
18 System.out.println(gwc.getResult());
19 }
20
21 }
可以直接在浏览器中访问 http://localhost:8080/hello
GreetingRouterTest.java
1 package com.cjs.example.restservice;
2
3 import org.junit.jupiter.api.Test;
4 import org.junit.jupiter.api.extension.ExtendWith;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.boot.test.context.SpringBootTest;
7 import org.springframework.http.MediaType;
8 import org.springframework.test.context.junit.jupiter.SpringExtension;
9 import org.springframework.test.web.reactive.server.WebTestClient;
10
11 @ExtendWith(SpringExtension.class)
12 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
13 public class GreetingRouterTest {
14
15 @Autowired
16 private WebTestClient webTestClient;
17
18 /**
19 * Create a GET request to test an endpoint
20 */
21 @Test
22 public void testHello() {
23 webTestClient.get()
24 .uri("/hello")
25 .accept(MediaType.TEXT_PLAIN)
26 .exchange()
27 .expectStatus().isOk()
28 .expectBody(String.class).isEqualTo("Hello, Spring!");
29 }
30
31 }
4. Reactor 核心特性
Mono: implements Publisher and returns 0 or 1 elements
Flux: implements Publisher and returns N elements
5. Spring Data Redis
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 4.0.0
5
6 org.springframework.boot
7 spring-boot-starter-parent
8 2.2.6.RELEASE
9
10
11 com.cjs.example
12 cjs-webflux-hello
13 0.0.1-SNAPSHOT
14 cjs-webflux-hello
15
16
17 1.8
18
19
20
21
22 org.springframework.boot
23 spring-boot-starter-data-redis-reactive
24
25
26 org.springframework.boot
27 spring-boot-starter-webflux
28
29
30
31 org.apache.commons
32 commons-pool2
33 2.8.0
34
35
36 com.alibaba
37 fastjson
38 1.2.67
39
40
41 org.projectlombok
42 lombok
43 true
44
45
46 org.springframework.boot
47 spring-boot-starter-test
48 test
49
50
51 org.junit.vintage
52 junit-vintage-engine
53
54
55
56
57 io.projectreactor
58 reactor-test
59 test
60
61
62
63
64
65
66 org.springframework.boot
67 spring-boot-maven-plugin
68
69
70
71
72
UserController.java
1 package com.cjs.example.webflux.controller;
2
3 import com.alibaba.fastjson.JSON;
4 import com.cjs.example.webflux.domain.User;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.data.redis.core.ReactiveHashOperations;
7 import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
8 import org.springframework.web.bind.annotation.*;
9 import reactor.core.publisher.Mono;
10
11 /**
12 * @author ChengJianSheng
13 * @date 2020-03-27
14 */
15 @RestController
16 @RequestMapping("/users")
17 public class UserController {
18
19
20 @Autowired
21 private ReactiveStringRedisTemplate reactiveStringRedisTemplate;
22
23 @GetMapping("/hello")
24 public Mono hello() {
25 return Mono.just("Hello, Reactive");
26 }
27
28 @PostMapping("/save")
29 public Mono saveUser(@RequestBody User user) {
30 ReactiveHashOperations hashOperations = reactiveStringRedisTemplate.opsForHash();
31 return hashOperations.put("USER_HS", String.valueOf(user.getId()), JSON.toJSONString(user));
32 }
33
34 @GetMapping("/info/{id}")
35 public Mono info(@PathVariable Integer id) {
36 ReactiveHashOperations reactiveHashOperations = reactiveStringRedisTemplate.opsForHash();
37 Mono hval = reactiveHashOperations.get("USER_HS", String.valueOf(id));
38 return hval.map(e->JSON.parseObject(e, User.class));
39 }
40
41 }
CoffeeController.java
1 package com.cjs.example.webflux.controller;
2
3 import com.cjs.example.webflux.domain.Coffee;
4 import org.springframework.data.redis.core.*;
5 import org.springframework.web.bind.annotation.GetMapping;
6 import org.springframework.web.bind.annotation.PathVariable;
7 import org.springframework.web.bind.annotation.RequestMapping;
8 import org.springframework.web.bind.annotation.RestController;
9 import reactor.core.publisher.Flux;
10 import reactor.core.publisher.Mono;
11
12 /**
13 * Spring WebFlux is the new reactive web framework introduced in Spring Framework 5.0.
14 * Unlike Spring MVC, it does not require the Servlet API, is fully asynchronous and non-blocking,
15 * and implements the Reactive Streams specification through the Reactor project.
16 *
17 * @author ChengJianSheng
18 * @date 2020-03-27
19 */
20 @RestController
21 @RequestMapping("/coffees")
22 public class CoffeeController {
23
24 private final ReactiveRedisOperations coffeeOps;
25
26 public CoffeeController(ReactiveRedisOperations coffeeOps) {
27 this.coffeeOps = coffeeOps;
28 }
29
30 @GetMapping("/getAll")
31 public Flux getAll() {
32 return coffeeOps.keys("*").flatMap(coffeeOps.opsForValue()::get);
33 }
34
35 @GetMapping("/info/{id}")
36 public Mono info(@PathVariable String id) {
37 ReactiveValueOperations valueOperations = coffeeOps.opsForValue();
38 return valueOperations.get(id);
39 }
40 }
最后,也是非常重要的一点:异步非阻塞并不会使程序运行得更快。WebFlux 并不能使接口的响应时间缩短,它仅仅能够提升吞吐量和伸缩性。
Spring WebFlux 是一个异步非阻塞的 Web 框架,所以,它特别适合应用在 IO 密集型的服务中,比如微服务网关这样的应用中。
Reactive and non-blocking generally do not make applications run faster.
6. Docs
springwebflux 页面_Spring WebFlux 入门相关推荐
- springwebflux 页面_Spring Webflux 响应式框架入门
@Componentpublic classBannerHandler { @AutowiredprivateBannerService bannerService;public MonogetLis ...
- springwebflux 页面_Spring Security: Webflux 默认配置
默认配置 所谓默认配置, 就是对Spring Security不做任何配置. 让它的自动配置起作用. 目的是对Spring Security 的默认行为有一个初步的直观的了解. 第一步: 使用Inte ...
- springboot异步注解_Spring Boot 2 :Spring Boot 中的响应式编程和 WebFlux 入门
[小宅按]Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕. WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可 ...
- springwebflux 页面_【SpringBoot WEB系列】WebFlux静态资源配置与访问
上一篇博文介绍SpringMVC的静态资源访问,那么在WebFlux中,静态资源的访问姿势是否一致呢 I. 默认配置 与SpringBoot的默认配置一样,WebFlux同样是classpath:/M ...
- requestmapping配置页面后_Spring MVC 入门指南(二):@RequestMapping用法详解
一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.x ...
- (转)Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门
http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html Spring 5.0 中发布了重量级组件 Webflux ...
- WebFlux入门极简
前言 之前讲述了国产微服务网关Soul底层用了 Webflux 技术,本文将将详细剖析其底层的技术细节. 本文知识点架构: 一.什么是WebFlux? 我们从Spring的官网拉下一点点就可以看到介绍 ...
- idea查询类_Spring Security入门(三): 基于自定义数据库查询的认证实战
0 引言 在笔者的上一篇文章中Spring Security入门(二):基于内存的认证一文中有提到过Spring Security实现自定义数据库查询需要你实现UserDetailsService接口 ...
- ih5怎么切换下一个页面_ih5快速入门(二)
快速入门第二章,使用一个简单案例来帮助大家,第一章所介绍的都会涉及到 大家先浏览一下案例 首先我们先看首页是如何做的,在这里会运用到动效 事件 同时也会在这里告诉大家音乐如何放进去,以及点击左上角可以 ...
最新文章
- MySQL 架构组成—存储引擎
- HTML5中的webSocket、ajax、http
- 响应式web之@media screen
- python listbox排序_Python3.3.2 tkinter ttk TreeView percolumn排序只按最后一列排序?
- 计算机wind10切换桌面wind7系统,win10一键切回win7桌面方法_Win10桌面切换成Win7界面的方法...
- ubuntu16.04下运行海康威视网络摄像头sdk(qtdemo)
- 目标检测、语义分割性能指标
- 实验七 构件图和部署图
- java二分法流程图,程序框图的法(二分法).ppt
- 行人属性识别 PETA数据集
- 可达编程 [语言题]中国身份证号码校验
- oracle经常考的题型是哪些,Oracle考试试题(带答案).doc
- Linux 常用命令整理(Centos7) (时区/正则/sed/htop/screen/ln/awk/……)
- 你也能看懂的:灰色预测算法
- 2018最新vue.js2.0完整视频教程12套
- [PTA]习题3-5 三角形判断
- 嵌入式linux指令
- cv2安装与基本函数
- 云承软件和云溪哪个好_「云承软件」广州市云承信息科技有限公司怎么样? - 职友集...
- 第3周练习 恺撒密码
热门文章
- 微服务架构_企业中的微服务:敌是友?
- wps分享为什么要登入_【知识点分享】钢筋上的螺纹有什么作用?为什么要有螺纹?...
- c++max函数怎么用_比函数还强大的Excel分列技巧,你知道怎么用吗
- android h5 禁止缩放,vue h5移动端禁止缩放代码
- GitHub Copilot 支持 IntelliJ IDEA啦,插件装起来!
- Facebook 分享 MySQL 5.6 到 8.0 的迁移经验
- 读完《Effective Java》后,总结了 50 条开发技巧
- 面试:字符串拼接,什么时候用StringBuilder?
- 国内技术原创氛围为什么那么差?记EAWorld(普元)是如何靠“借鉴”产出原创文章的!
- 坐标系转换公式_【技术】西安80坐标与地方坐标系的转换方法技巧