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);
  }




}


posted @   翻蹄亮掌一皮鞋  阅读(740)  评论(0编辑  收藏  举报
编辑推荐:
· 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)
点击右上角即可分享
微信分享提示