iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >springboot3+r2dbc响应式编程实践
  • 151
分享到

springboot3+r2dbc响应式编程实践

2024-04-02 19:04:59 151人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录r2dbc工程依赖配置文件配置类beanDAOcontrollerSpring Boot3已经M1了,最近群佬们也开始蠢蠢欲动的开始整活Reactive+spring Boot3

Spring Boot3已经M1了,最近群佬们也开始蠢蠢欲动的开始整活Reactive+spring Boot3,跟着大家的步伐,我也来整一篇工程入门,我们将用java17+Spring Boot3+r2dbc+Reactive栈来讲述,欢迎大家来讨论。(关于响应式,请大家异步到之前的文章里,有详细介绍。)

r2dbc

Reactor还有基于其之上的Spring WEBFlux框架。包括vert.x,rxjava等等reactive技术。我们实际上在应用层已经有很多优秀的响应式处理框架。

但是有一个问题就是所有的框架都需要获取底层的数据,而基本上关系型数据库的底层读写都还是同步的。

为了解决这个问题,出现了两个标准,一个是oracle提出的 ADBC (Asynchronous Database Access api),另一个就是Pivotal提出的R2DBC (Reactive Relational Database Connectivity)。

R2DBC是基于Reactive Streams标准来设计的。通过使用R2DBC,你可以使用reactive API来操作数据。

同时R2DBC只是一个开放的标准,而各个具体的数据库连接实现,需要实现这个标准。

今天我们以r2dbc-h2为例,讲解一下r2dbc在Spring webFlux中的使用。

工程依赖

以下是 pom.xml清单

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="Http://Maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0-M1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>wang.datahub</groupId>
    <artifactId>SpringBoot3Demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot3demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-r2dbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-Redis-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-groovy-templates</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-h2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

        <dependency>
            <groupId>Mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
<!--            <version>3.4.14</version>-->
<!--            <scope>compile</scope>-->
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>

</project>

配置文件

这里我们只配置了r2dbc链接信息

配置类

用于配置默认链接,创建初始化数据

package wang.datahub.springboot3demo.config;

import io.Netty.util.internal.StringUtil;
import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Flux;
import static io.r2dbc.spi.ConnectionFactoryOptions.*;

@Configuration
@ConfigurationProperties(prefix = "r2dbc")
public class DBConfig {

    private String url;
    private String user;
    private String passWord;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Bean
    public ConnectionFactory connectionFactory() {
        System.out.println("url ==> "+url);
        ConnectionFactoryOptions baseOptions = ConnectionFactoryOptions.parse(url);
        ConnectionFactoryOptions.Builder ob = ConnectionFactoryOptions.builder().from(baseOptions);
        if (!StringUtil.isNullOrEmpty(user)) {
            ob = ob.option(USER, user);
        }
        if (!StringUtil.isNullOrEmpty(password)) {
            ob = ob.option(PASSWORD, password);
        }
        return ConnectionFactories.get(ob.build());
    }

    @Bean
    public CommandLineRunner initDatabase(ConnectionFactory cf) {

        return (args) ->
                Flux.from(cf.create())
                        .flatMap(c ->
                                Flux.from(c.createBatch()
                                                .add("drop table if exists Users")
                                                .add("create table Users(" +
                                                        "id IDENTITY(1,1)," +
                                                        "firstname varchar(80) not null," +
                                                        "lastname varchar(80) not null)")
                                                .add("insert into Users(firstname,lastname)" +
                                                        "values('Jacky','Li')")
                                                .add("insert into Users(firstname,lastname)" +
                                                        "values('Doudou','Li')")
                                                .add("insert into Users(firstname,lastname)" +
                                                        "values('Maimai','Li')")
                                                .execute())
                                        .doFinally((st) -> c.close())
                        )
                        .log()
                        .blockLast();
    }

}

bean

创建用户bean

package wang.datahub.springboot3demo.bean;

import org.springframework.data.annotation.Id;

public class Users {
    @Id
    private Long id;
    private String firstname;
    private String lastname;

    public Users(){

    }

    public Users(Long id, String firstname, String lastname) {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                '}';
    }
}

DAO

dao代码清单如下,包含查询列表、按id查询,以及创建用户等操作

package wang.datahub.springboot3demo.dao;

import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Query;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import wang.datahub.springboot3demo.bean.Users;

import static org.springframework.data.r2dbc.query.Criteria.where;
import static org.springframework.data.relational.core.query.Query.query;

@Component
public class UsersDao {
    private ConnectionFactory connectionFactory;
    private R2dbcEntityTemplate template;

    public UsersDao(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
        this.template = new R2dbcEntityTemplate(connectionFactory);
    }

    public Mono<Users> findById(long id) {

        return this.template.selectOne(query(where("id").is(id)),Users.class);

//        return Mono.from(connectionFactory.create())
//                .flatMap(c -> Mono.from(c.createStatement("select id,firstname,lastname from Users where id = $1")
//                                .bind("$1", id)
//                                .execute())
//                        .doFinally((st) -> close(c)))
//                .map(result -> result.map((row, meta) ->
//                        new Users(row.get("id", Long.class),
//                                row.get("firstname", String.class),
//                                row.get("lastname", String.class))))
//                .flatMap( p -> Mono.from(p));
    }

    public Flux<Users> findAll() {
        return this.template.select(Users.class).all();
//        return Mono.from(connectionFactory.create())
//                .flatMap((c) -> Mono.from(c.createStatement("select id,firstname,lastname from users")
//                                .execute())
//                        .doFinally((st) -> close(c)))
//                .flatMapMany(result -> Flux.from(result.map((row, meta) -> {
//                    Users acc = new Users();
//                    acc.setId(row.get("id", Long.class));
//                    acc.setFirstname(row.get("firstname", String.class));
//                    acc.setLastname(row.get("lastname", String.class));
//                    return acc;
//                })));
    }

    public Mono<Users> createAccount(Users account) {

        return Mono.from(connectionFactory.create())
                .flatMap(c -> Mono.from(c.beginTransaction())
                        .then(Mono.from(c.createStatement("insert into Users(firstname,lastname) values($1,$2)")
                                .bind("$1", account.getFirstname())
                                .bind("$2", account.getLastname())
                                .returnGeneratedValues("id")
                                .execute()))
                        .map(result -> result.map((row, meta) ->
                                new Users(row.get("id", Long.class),
                                        account.getFirstname(),
                                        account.getLastname())))
                        .flatMap(pub -> Mono.from(pub))
                        .delayUntil(r -> c.commitTransaction())
                        .doFinally((st) -> c.close()));

    }

    private <T> Mono<T> close(Connection connection) {
        return Mono.from(connection.close())
                .then(Mono.empty());
    }
}

controller

controller代码清单如下,包含了查询列表、按id查询,以及创建用户等操作

package wang.datahub.springboot3demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import wang.datahub.springboot3demo.bean.Users;
import wang.datahub.springboot3demo.dao.UsersDao;

@RestController
public class UsersController {
    @Autowired
    private final UsersDao usersDao;

    public UsersController(UsersDao usersDao) {
        this.usersDao = usersDao;
    }

    @GetMapping("/users/{id}")
    public Mono<ResponseEntity<Users>> getUsers(@PathVariable("id") Long id) {

        return usersDao.findById(id)
                .map(acc -> new ResponseEntity<>(acc, HttpStatus.OK))
                .switchIfEmpty(Mono.just(new ResponseEntity<>(null, HttpStatus.NOT_FOUND)));
    }

    @GetMapping("/users")
    public Flux<Users> getAllAccounts() {
        return usersDao.findAll();
    }

    @PostMapping("/createUser")
    public Mono<ResponseEntity<Users>> createUser(@RequestBody Users user) {
        return usersDao.createAccount(user)
                .map(acc -> new ResponseEntity<>(acc, HttpStatus.CREATED))
                .log();
    }
}

启动类清单:

package wang.datahub.springboot3demo;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import wang.datahub.springboot3demo.config.DBConfig;


@SpringBootApplication
@EnableConfigurationProperties(DBConfig.class)
public class WebFluxR2dbcApp {
    public static void main(String[] args) {
        SpringApplication.run(WebFluxR2dbcApp.class, args);
    }
}

好了,致此我们整个 Demo 就实现完成了

参考链接:

https://zhuanlan.zhihu.com/p/299069835

到此这篇关于springboot3+r2dbc响应式编程实践的文章就介绍到这了,更多相关springboot3 r2dbc响应式编程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: springboot3+r2dbc响应式编程实践

本文链接: https://www.lsjlt.com/news/138869.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • springboot3+r2dbc响应式编程实践
    目录r2dbc工程依赖配置文件配置类beanDAOcontrollerSpring boot3已经M1了,最近群佬们也开始蠢蠢欲动的开始整活Reactive+Spring Boot3...
    99+
    2022-11-13
  • 响应式编程:PHP教程中的算法实践分享。
    响应式编程是一种面向数据流和变化传播的编程范式。它的目的是使代码更加可读、可维护和可扩展。PHP作为一种流行的后端语言,也可以使用响应式编程来增强代码的质量。在本篇文章中,我们将介绍响应式编程的概念和在PHP中的实践经验。 响应式编程的...
    99+
    2023-07-22
    教程 编程算法 响应
  • 响应式文件处理:Java并发编程的最佳实践
    在现代应用程序中,文件处理是非常普遍的任务。然而,随着文件数量和大小的增加,传统的文件处理方式可能会变得缓慢和低效。为了解决这个问题,我们可以采用响应式文件处理的方式,它是一种使用Java并发编程的最佳实践。 响应式编程是一种基于异步数据...
    99+
    2023-10-17
    并发 响应 文件
  • 解密响应式编程:Java与Linux面试中的应用和实践!
    响应式编程是一种基于异步数据流的编程模式,它可以帮助我们更好地处理复杂的数据流。在Java和Linux面试中,响应式编程的应用越来越普遍。在本文中,我们将探讨响应式编程的概念以及如何在Java和Linux中应用和实践。 一、响应式编程的概念...
    99+
    2023-09-29
    响应 面试 linux
  • 数据类型和异步编程:Java中响应式编程的最佳实践
    Java是一门广泛应用于企业级应用程序开发的编程语言。Java语言的强类型特性对于数据类型的定义和处理有着很好的支持。而异步编程技术则可以更好地处理大规模数据和复杂业务逻辑。本篇文章将介绍数据类型和异步编程在Java中的最佳实践,以帮助Ja...
    99+
    2023-10-21
    数据类型 响应 异步编程
  • vue2.0响应式编程实例分析
    本篇内容介绍了“vue2.0响应式编程实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! vue2....
    99+
    2022-10-19
  • Vue.js响应式编程实例分析
    这篇文章主要介绍了Vue.js响应式编程实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue.js响应式编程实例分析文章都会有所收获,下面我们一起来看看吧。响应式编程展示数据,对象例子:var ...
    99+
    2023-06-27
  • Spring响应式编程实例分析
    今天小编给大家分享一下Spring响应式编程实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 前言了解响应式编程,...
    99+
    2023-07-02
  • Project Reactor 响应式范式编程
    目录什么是响应式编程?Java中的响应式编程Project Reactor基本概念核心组件代码示例MonoFlux什么是响应式编程? 响应式编程是一种编程范式,它关注数据的变化和传...
    99+
    2023-05-14
    Project Reactor 响应式 Project Reactor范式编程
  • Java中的索引数据类型如何应用于响应式编程的实践中?
    随着互联网的快速发展,人们对数据的处理需求越来越高。在Java编程中,索引数据类型是非常重要的一种数据类型,它能够帮助我们更加高效地处理数据。同时,响应式编程也是近年来比较流行的一种编程模式,它可以在数据变化时自动更新UI,提高程序的响应...
    99+
    2023-09-09
    响应 索引 数据类型
  • 浅谈Rx响应式编程
    目录一、Observable二、高阶函数三、快递盒模型3.1、快递盒模型1:fromEvent3.2、快递盒模型2:interval四、高阶快递盒五、销毁快递盒5.1、销毁快递盒——...
    99+
    2022-11-12
  • 什么是响应式编程
    本篇内容介绍了“什么是响应式编程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!最近几年,随着Go、Node...
    99+
    2022-10-19
  • Spring-webflux 响应式编程的实例详解
    目录1. 前言2. Spring-webflux简介3. 什么是“响应式”4. Spring-webflux的响应式API5. Spring MVC 还是 W...
    99+
    2022-11-13
  • ASP 和 Spring 教程:如何实现响应式编程?
    在当今的软件开发领域中,响应式编程已经成为一种非常流行的编程范式。ASP 和 Spring 是两个非常流行的 Web 框架,本篇文章将介绍如何使用 ASP 和 Spring 实现响应式编程。 什么是响应式编程? 响应式编程是一种基于事件驱...
    99+
    2023-10-29
    响应 spring 教程
  • 响应式编程中使用Java索引数据类型的最佳实践是什么?
    随着计算机技术的不断发展,我们需要更高效、更快速的编程方式来满足应用程序的需求。响应式编程就是这样一种新的编程方式,它可以让我们更加高效地处理异步事件流,提高代码的可读性和可维护性。在响应式编程中,使用Java索引数据类型是一种非常重要的...
    99+
    2023-09-09
    响应 索引 数据类型
  • NPM响应式设计:Java IDE的最佳实践
    随着移动互联网的普及,响应式设计已经成为了现代Web开发的必备技能。而在Java IDE的开发中,NPM响应式设计也越来越受到关注。在本文中,我们将介绍NPM响应式设计的基础知识,并探讨如何在Java IDE中应用最佳实践。 什么是NPM...
    99+
    2023-09-29
    ide npm 响应
  • 实时响应关键字搜索:GO语言编程的最佳实践?
    随着互联网的快速发展,搜索引擎成为人们获取信息的重要途径之一。搜索引擎的效率和准确性对于用户体验至关重要,因此实时响应关键字搜索成为了搜索引擎的重要功能之一。GO语言作为一门高效的编程语言,其在实时响应关键字搜索方面也有着不错的表现。 本...
    99+
    2023-06-22
    响应 实时 关键字
  • 响应时间王者:PHP中HTTP异步编程的最佳实践
    PHP中的HTTP异步编程是一种高效的方式,可以大大提高Web应用程序的响应速度。在本文中,我们将介绍PHP中HTTP异步编程的最佳实践,以帮助您更好地理解和使用这种技术。 一、什么是HTTP异步编程? HTTP异步编程是一种技术,可以在P...
    99+
    2023-10-03
    http 异步编程 响应
  • Project Reactor响应式编程是什么
    这篇文章主要介绍了Project Reactor响应式编程是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Project Reactor响应式编程是什么文章都会有所收获,下面我们一起来看...
    99+
    2023-07-05
  • 如何在GO语言中实现响应式编程?
    随着现代软件开发的不断发展,越来越多的开发人员开始关注响应式编程。响应式编程是一种编程范式,它强调程序应该根据数据流的变化做出响应,而不是通过手动编写代码来实现数据流的变化。这种编程范式可以帮助开发人员更好地处理异步事件和数据流,从而提高...
    99+
    2023-06-21
    响应 容器 npm
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作