Spring WebFlux整合Spring Data R2DBC实现响应式编程

Spring WebFlux和Spring Data R2DBC是Spring Framework生态系统中的两个重要组件,用于构建响应式应用程序和与关系型数据库交互。

  1. Spring WebFlux: Spring WebFlux是Spring Framework 5中引入的响应式编程框架。与传统的Servlet API不同,Spring WebFlux提供了一种基于反应式流的方式来处理Web请求和响应。它支持异步和非阻塞的IO操作,使得应用程序能够更有效地处理高并发的情况。

    特点:

    • 响应式:使用反应式流处理请求和响应,支持异步和非阻塞的IO操作。
    • 高性能:能够处理高并发的情况,提供了高效的事件驱动模型。
    • 弹性:能够轻松地处理流量激增和负载均衡。
  2. Spring Data R2DBC: Spring Data R2DBC是Spring Data项目的一部分,专门用于与关系型数据库进行交互。与传统的Spring Data JPA不同,Spring Data R2DBC支持异步和非阻塞的数据库访问,与Spring WebFlux完美契合,从而构建全栈响应式应用程序。

    特点:

    • 非阻塞:基于Reactive Streams标准实现,支持异步和非阻塞的数据库访问。
    • 异步API:提供了异步的Repository API,允许在响应式流中处理数据库操作。
    • 响应式编程:与Spring WebFlux等响应式框架集成,支持响应式编程模型。
    • 支持的数据库:支持使用R2DBC(Reactive Relational Database Connectivity)规范的关系型数据库,如PostgreSQL、MySQL等。

综上所述,Spring WebFlux和Spring Data R2DBC为构建响应式应用程序提供了强大的支持,使开发人员能够利用异步和非阻塞的编程模型构建高性能、弹性的应用程序,并与关系型数据库进行高效交互。

注意:启动类需要添加该注解,指定存放Repository类的目录

@EnableR2dbcRepositories(basePackages = "com.test.service.postgres")

1、引用Maven依赖

<!-- webflux reactive -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.7.9</version>
</dependency>
<!-- r2db -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-r2dbc</artifactId>
    <version>2.7.9</version>
</dependency>
<!-- postgresql -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>r2dbc-postgresql</artifactId>
</dependency>

2、YAML配置

spring:
  r2dbc:
    url: r2dbc:postgresql://localhost:5432/database_name
    username: your_username
    password: your_password
    pool:
      initialSize: 10
      maxSize: 20
      maxIdleTime: 30m
      validationQuery: "SELECT 1"
      connectionTimeout: 10s
      maxLifeTime: 10m

3、用户表

/**
 * @author Lucas
 * date 2024/2/15 18:46
 * description 用户表
 */
@Data
@Table(name = "sys_user")
public class User implements Persistable<String> {
    @Id
    private String id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    @Transient
    private boolean isNew;

    @Override
    @Transient
    public boolean isNew() {
        return this.isNew || id == null;
    }

    public User setAsNew(){
        this.isNew = true;
        return this;
    }
}

4、用户表Repository

/**
 * @author Lucas
 * date 2024/2/15 19:39
 * description 用户表Repository
 */
@Repository
public interface UserRepository extends R2dbcRepository<User, String> {

    /**
     * 判断是否存在
     * @param name
     * @return
     */
    Mono<Integer> countByName(String name);

    /**
     * 修改
     * @param Id
     * @param name
     * @param age
     * @return
     */
    @Modifying/*查询不需要加该注解*/
    @Query("update sys_user set name = :name,age = :age where id = :Id")
    Mono<Boolean> updateUser(String Id, String name, Integer age);

    /**
     * 获取该年龄所有用户
     * @param age
     * @return
     */
    Flux<User> findByAge(Integer age);
}

5、用户ServiceImpl

/**
 * @author Lucas
 * date 2024/2/15 19:48
 * description 用户ServiceImpl
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    @Override
    public Mono<Boolean> saveUser(User user) {
        return userRepository.countByName(user.getName()).flatMap(i -> {
            if (i > 0) {
                return Mono.error(new Exception("该用户名已存在,请勿重复创建"));
            }
            //setAsNew()的作用主要是自己生成主键ID执行新增,不然传ID会执行修改操作报错ID不存在,自增ID不需要该方法
            return userRepository.save(user.setAsNew()).map(r -> true);
        });
    }

    @Override
    public Mono<Boolean> updateUser(User user) {
        return userRepository.updateUser(user.getId(), user.getName(), user.getAge());
    }

    @Override
    public Mono<List<User>> getUserList(Integer age) {
        return userRepository.findByAge(age).collectList();
    }
}

6、用户Service

/**
 * @author Lucas
 * date 2024/2/15 19:47
 * description 用户Service
 */
public interface UserService {


    /**
     * 新增用户
     * @param user
     * @return
     */
    Mono<Boolean> saveUser(User user);

    /**
     * 修改用户
     * @param user
     * @return
     */
    Mono<Boolean> updateUser(User user);

    /**
     * 获取指定年龄所有用户
     * @param age
     * @return
     */
    Mono<List<User>> getUserList(Integer age);
}

7、用户Controller

/**
 * @author Lucas
 * date 2024/2/12 18:07
 * description 用户Controller
 */
@Slf4j
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    /**
     * 新增用户
     * @param user
     * @return
     */
    @RequestMapping(value = "/saveUser", method = RequestMethod.POST, headers = {"X-HTTP-Method-Override=POST"})
    public Mono<Boolean> saveUser(@RequestBody @Validated User user) {
        return userService.saveUser(user);
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    @RequestMapping(value = "/updateUser", method = RequestMethod.POST, headers = {"X-HTTP-Method-Override=POST"})
    public Mono<Boolean> updateUser(@RequestBody @Validated User user) {
        return userService.updateUser(user);
    }

    /**
     * 获取指定年龄所有用户
     * @param age
     * @return
     */
    @RequestMapping(value = "/getUserList", method = RequestMethod.POST, headers = {"X-HTTP-Method-Override=GET"})
    public Mono<List<User>> getUserList(@RequestParam @NotNull Integer age) {
        return userService.getUserList(age);
    }
}

Spring Data R2DBCSpring框架为响应式数据库操作提供的模块。R2DBC是Reactive Relational Database Connectivity的缩写,它是一种基于响应式编程模型的数据库访问方式。相比传统的阻塞式JDBC,R2DBC允许在异步非阻塞的环境下进行数据库操作。 使用Spring Data R2DBC,你可以通过定义接口和方法来实现对响应式数据库的操作。它提供了一套统一的API,支持常见的关系型数据库(如MySQL、PostgreSQL等)。 以下是一个简单的示例,展示了如何使用Spring Data R2DBC进行数据库操作: ```java import org.springframework.data.annotation.Id; import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Table; @Table("users") public class User { @Id private Long id; @Column("name") private String name; // Getters and setters } @Repository public interface UserRepository extends ReactiveCrudRepository<User, Long> { Flux<User> findByName(String name); } @Service public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public Flux<User> findUsersByName(String name) { return userRepository.findByName(name); } } ``` 在上述示例中,我们定义了一个User实体类,并使用@Table和@Id注解进行映射。然后创建了一个UserRepository接口,继承自ReactiveCrudRepository,这个接口提供了一些基本的CRUD方法,并支持响应式的返回类型。最后,在UserService中使用UserRepository进行数据库操作。 通过Spring Data R2DBC,你可以使用像Flux和Mono这样的响应式类型来处理数据流,以实现异步非阻塞的数据库操作。这使得你可以更好地利用系统资源,提高系统的响应性能。 希望这个简单的示例能够帮助你理解Spring Data R2DBC的基本用法。如果需要更详细的信息,可以查阅Spring官方文档或参考其他资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值