Spring Webflux
什么是Spring Webflux
Spring Webflux是 Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用当前一种比较流程响应式编程出现的框架。
响应式编程
响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
反应式 API
与Spring Mvc不同
SpringMVC 采用命令式编程,Webflux 采用异步响应式编程
核心控制器
实现方式
Spring Webflux 实现方式有两种:注解编程模型和函数式编程模型
注解编程模型
//数据库表
/*
Navicat Premium Data Transfer
Source Server : school
Source Server Type : MySQL
Source Server Version : 80022
Source Host : localhost:3306
Source Schema : school
Target Server Type : MySQL
Target Server Version : 80022
File Encoding : 65001
Date: 08/11/2021 22:10:28
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for grade
-- ----------------------------
DROP TABLE IF EXISTS `grade`;
CREATE TABLE `grade` (
`gradeId` int(0) NOT NULL AUTO_INCREMENT,
`gradeName` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`gradeId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of grade
-- ----------------------------
INSERT INTO `grade` VALUES (1, 'S1');
INSERT INTO `grade` VALUES (2, 'Y1');
SET FOREIGN_KEY_CHECKS = 1;
//pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
//application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/school?serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
package com.fly.webflux.entity;
public class Grade {
private Integer gradeId;
private String gradeName;
@Override
public String toString() {
return "Grade{" +
"gradeId=" + gradeId +
", gradeName='" + gradeName + '\'' +
'}';
}
public Integer getGradeId() {
return gradeId;
}
public void setGradeId(Integer gradeId) {
this.gradeId = gradeId;
}
public String getGradeName() {
return gradeName;
}
public void setGradeName(String gradeName) {
this.gradeName = gradeName;
}
}
package com.fly.webflux.dao;
import com.fly.webflux.entity.Grade;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface GradeDao {
Grade getGradeById(Integer gradeId);
List<Grade> getAll();
}
package com.fly.webflux.service;
import com.fly.webflux.entity.Grade;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface GradeService {
Mono<Grade> getGradeById(Integer gradeId);
Flux<Grade> getAll();
}
package com.fly.webflux.service.impl;
import com.fly.webflux.dao.GradeDao;
import com.fly.webflux.entity.Grade;
import com.fly.webflux.service.GradeService;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@Service
public class GradeServiceImpl implements GradeService {
@Resource
private GradeDao gradeDao;
@Override
public Mono<Grade> getGradeById(Integer gradeId) {
return Mono.justOrEmpty(gradeDao.getGradeById(gradeId));
}
@Override
public Flux<Grade> getAll() {
return Flux.fromIterable(gradeDao.getAll());
}
}
package com.fly.webflux.controller;
import com.fly.webflux.entity.Grade;
import com.fly.webflux.service.GradeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@RestController
public class GradeController {
@Resource
private GradeService gradeService;
@GetMapping("/grade/{gradeId}")
public Mono<Grade> getGradeById(@PathVariable Integer gradeId) {
return gradeService.getGradeById(gradeId);
}
@GetMapping("/grade/getall")
public Flux<Grade> getAll() {
return gradeService.getAll();
}
}
函数式编程模型
复制刚才的工程,删掉controller
package com.fly.webflux.handler;
import com.fly.webflux.entity.Grade;
import com.fly.webflux.service.GradeService;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @author 26414
*/
@Component
public class GradeHandler {
private final GradeService gradeService;
public GradeHandler(GradeService gradeService) {
this.gradeService = gradeService;
}
public Mono<ServerResponse> getGradeById(ServerRequest request) {
Integer gradeId = Integer.parseInt(request.pathVariable("gradeId"));
Mono<Grade> grade = gradeService.getGradeById(gradeId);
return
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(grade,Grade.class);
}
//没有ServerRequest request这个参数设置路由时检测不到方法
public Mono<ServerResponse> getAll(ServerRequest request) {
Flux<Grade> grades = gradeService.getAll();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(grades,Grade.class);
}
}
package com.fly.webflux.handler;
import com.fly.webflux.service.GradeService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import javax.annotation.Resource;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
@Configuration
public class GradeRouter {
@Resource
private GradeService gradeService;
@Bean
public RouterFunction<ServerResponse> routingFunction() {
GradeHandler handler = new GradeHandler(gradeService);
return RouterFunctions.route(
GET("/grade/{gradeId}").and(accept(APPLICATION_JSON)),handler::getGradeById)
.andRoute(GET("/grade").and(accept(APPLICATION_JSON)),handler::getAll);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)