您现在的位置是:首页 > 正文

Spring-WebFlux简介与使用

2024-02-29 11:03:11阅读 0


简介

Spring WebFlux是Spring Framework 5.0中引入的新的反应式Web框架。 与Spring MVC不同,它不需要Servlet API,完全异步和非阻塞, 并通过Reactor项目实现Reactive Streams规范。 并且可以在诸如Netty,Undertow和Servlet 3.1+容器的服务器上运行。

Reactor中的Mono和Flux

Flux 和 Mono 是 Reactor 中的两个基本概念。Flux 表示的是包含 0 到 N 个元素的异步序列。 在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。 当消息通知产生时,订阅者中对应的方法 onNext(), onComplete()和 onError()会被调用。Mono 表示的是包含 0 或者 1 个元素的异步序列。 该序列中同样可以包含与 Flux 相同的三种类型的消息通知。Flux 和 Mono 之间可以进行转换。 对一个 Flux 序列进行计数操作,得到的结果是一个 Mono对象。把两个 Mono 序列合并在一起,得到的是一个 Flux 对象。 了解更多

WebFlux的使用方式

图片简介

如图所示,WebFlux支持两种编程方式

  • 基于SpringMvc注解@Controller
  • 基于Java8 lambda样式路由和处理

使用WebFlux需要单独引用它的依赖,我使用的springboot,依赖如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--reactor的测试依赖-->
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

示例

  • 基于SpringMvc注解

    与使用SpringMvc不同的是使用SpringWebFlux同一使用Mono<>,Flux<>对象同意返回数据,如下

    @RestController
    @RequestMapping("/api/user")
    public class WebFluxController {
    
        private Map<Long,User> map = new HashMap<Long,User>(10);
        @PostConstruct
        public void init(){
            map.put(1L,new User(1,"admin","admin"));
            map.put(2L,new User(1,"admin2","admin2"));
            map.put(3L,new User(1,"admin3","admin3"));
        }
        @GetMapping("/getAll")
        public Flux<User> getAllUser(){
            return Flux.fromIterable(map.entrySet().stream().map(Map.Entry::getValue)
                    .collect(Collectors.toList()));
        }
        @GetMapping("/{id}")
        public Mono<User> getUserById(@PathVariable("id") Long id){
            return Mono.just(map.get(id));
        }
        @PostMapping("/save")
        public Mono<ResponseEntity<String>> save(@RequestBody User user){
            map.put(user.getUid(),user);
            return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED));
        }
    }

    具体实现代码可查看springboot-webflux

  • 基于功能

    处理请求的类,实现具体的业务逻辑,接口 ServerRequest 表示的是一个 HTTP 请求体。通过ServerRequest 对象可获取到请求的相关信息,如请求路径、查询参数和请求内容等。方法 的返回值是一个 Mono对象。接口 ServerResponse 用来表示 HTTP 响应。ServerResponse 中包含了很多静态方法来创建不同 HTTP 状态码的响应对象

    @Component
    public class UserHandler {
    
        private IUserService userService;
        @Autowired
        public UserHandler(IUserService userService) {
            this.userService = userService;
        }
    
        public Mono<ServerResponse> getAllUser(ServerRequest serverRequest){
            Flux<User> allUser = userService.getAllUser();
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class);
        }
    
        public Mono<ServerResponse> getUserById(ServerRequest serverRequest){
            //获取url上的id
            Long uid = Long.valueOf(serverRequest.pathVariable("id"));
            Mono<User> user = userService.getUserById(uid);
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(user,User.class);
        }
    
        public Mono<ServerResponse> saveUser(ServerRequest serverRequest){
            Mono<User> user = serverRequest.bodyToMono(User.class);
            return ServerResponse.ok().build(userService.saveUser(user));
        }
    
    }

    为Handler类添加路由信息,

    @Configuration
    public class RoutingConfiguration {
    
        @Bean
        public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler){
            return route(GET("/api/user").and(accept(MediaType.APPLICATION_JSON)),userHandler::getAllUser)
                    .andRoute(GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)),userHandler::getUserById)
                    .andRoute(POST("/api/save").and(accept(MediaType.APPLICATION_JSON)),userHandler::saveUser);
        }
    
    }

    具体实现代码可查看springboot-webflux-functional

网站文章

  • Java NIO 关键概念之 Buffer

    Java NIO 关键概念之 Buffer

    一、前言 Java NIO 的三大关键概念之一是 Buffer,在一些文章/源代码中,我们也经常会看到 Buffer 相关的信息。Buffer 到底是什么,Buffer 的基本使用方法是什么,这是本文主要要说的。

    2024-02-29 11:03:04
  • webpack

    webpack

    vue2.0---webpack的配置一、webpack简介二、安装 Webpack三、创建项目四、OADER一、webpack简介Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系...

    2024-02-29 11:02:37
  • 合理使用 inline来优化程序 尽可能减少临时对象 尽可能使用初始化列表

    合理使用 inline来优化程序 尽可能减少临时对象 尽可能使用初始化列表

    调用 函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序 内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前 要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执 行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特 别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率 问题更为重要。引入内联函数

    2024-02-29 11:02:30
  • 手机端font-size:62.5%原理

    原理: 是根据根节点html的默认字体大小font-size来计算的,以此进行rem的初始值设置。实现对不同屏幕宽度的适配。(100px/16px=6.25=625%, 100代表100px,这里是以...

    2024-02-29 11:02:24
  • Docker Stack yaml 使用 image 指定镜像

    Docker Stack yaml 使用 image 指定镜像

    `image` 用于指定启动容器的镜像。镜像必须遵循开放容器规范可寻址格式,如 `[/][/][:|@]`。 其实还可以使用镜像id,格式为 `sha256:`。

    2024-02-29 11:02:19
  • POJ 1330 Nearest Common Ancestors 最近公共祖先模板/在线/离线

    POJ 1330 Nearest Common Ancestors 最近公共祖先模板/在线/离线

    题意:求树上两个节点的最近公共祖先算法一:tarjanLCA(u) {  Make-Set(u)  ancestor[Find-Set(u)]=u  //设置u所在集合的祖先  对于u的每一个孩子v {   LCA(v)   Union(v,u)              //把v生成的子集并入u中   ancestor[Find-Set(u)]=u

    2024-02-29 11:01:47
  • fonts.conf

    &lt;?xml version="1.0"?&gt; &lt;!DOCTYPE fontconfig SYSTEM "fonts.dtd"&gt; &lt;!-- /etc/fonts.conf file to configure system font access --&gt; &lt;fontconfig&gt; &lt;!--    The intent of this standa

    2024-02-29 11:01:40
  • python - 编程中【工厂模式】和【单例模式】有什么区别以及代码示例

    python - 编程中【工厂模式】和【单例模式】有什么区别以及代码示例

    工厂模式和单例模式都是面向对象编程中常用的设计模式。

    2024-02-29 11:01:34
  • 剑指offer 30. 栈的压入、弹出序列

    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。 假设压入栈的所有数字均不相等。 例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。 注意:若两个序列为空或长度不等则视为并不是一个栈的压入、弹出序列。 样例 输入:[1,2,3,4,5] [4,5,...

    2024-02-29 11:01:06
  • 第四章 应用SysML基本特性集的汽车示例 P2(断更)|系统建模语言SysML实用指南学习

    第四章 应用SysML基本特性集的汽车示例 P2(断更)|系统建模语言SysML实用指南学习

    第四章暂时搁置,文章很多细节未给出,同时使用的CSM试用版有限制

    2024-02-29 11:00:59