java web jdbc例子_Spring WebFlux 和java2-jdbc结合案例

Spring WebFlux是一种创建非阻塞REST应用程序的好方法。但是,一般人开始使用WebFlux时都会遇到的一个问题就是JDBC连接池是一种阻塞方式,如何让JDBC连接池堵塞不会对整个请求的访问路径造成堵塞呢?

像Cassandra或Couchbase这样新数据库都提供了非阻塞的驱动程序。比如Couchbase的驱动程序就是使用RXJava。NoSQL数据库非常棒,但由于各种原因,实际中可能并不都是使用它们。而关系数据库在创建驱动程序异步方面还要付出一些努力,比如Oracle正在推出异步数据库驱动ADBA。不幸的是,这种异步数据库驱动真的还处于早期阶段。

但是现在情况下是,只要你想使用JVM和SQL数据库进行交互,你就会需要使用通常的阻塞JDBC驱动程序。幸运的是,如果使用Spring WebFlux构建非阻塞应用程序,那么reactor-core和rxjava2可以帮助你实现异步的反应式的ReactiveStreams。

这就意味着您可以使用David Moten的rxjava2-jdbc库,尽管它采取的是普通堵塞式的JDBC驱动程序,但是可以让我们的应用程序以不会堵塞的方式与数据库进行交互。它是通过在不同线程上调度背后的阻塞来实现的 此外,它还具有DSL,可以将SQL语句和结果建模为流Stream,这些整合都使得响应式编程变得更简单。

Rxjava2-jdbc还提供了非阻塞连接池,通常在阻塞应用程序中,如果线程被阻塞,会一直到有可用的连接才会继续。但是这对于非阻塞应用程序来说却是一个问题,因为非堵塞应用会启动新的数据库连接,这将很快耗尽所有数据库连接线程,并将美妙的非阻塞应用程序变为笨重的阻塞应用程序。在rxjava2-jdbc中,其连接池将返回由连接池控制的一个Single,这意味着,不是为每次查询分配一个线程,查询会订阅连接池,并在有可用时接收连接 - 同时不会阻塞应用程序的线程!

说了这么多,还是看看示例吧,下面我创建了一个使用Spring WebFlux,rxjava2-jdbc和H2的示例。该示例是使用嵌入式H2数据库的简单REST应用程序。它源码在这里:https://github.com/netifi/webflux-rxjava2-jdbc-example。

这个例子有两个对象:第一个是一个Employee对象,它包含关于员工的信息,包括:名字,姓氏和部门ID。第二个对象是Department对象,其中包含有关不同部门的信息。该应用程序具有restful的端点,用于部门的员工和列表操作的基本创建,读取,删除和列表操作。

运行示例

运行该示例很简单,可以使用以下命令完成:

./gradlew clean run

该命令将配置数据库并使用Spring Boot启动WebFlux应用程序。该示例不需要运行servlet容器,而是使用Netty。如果您想测试并查看示例是否已启动并正在运行,则可以运行以下curl命令:

curl localhost:8080 / employees

如果运行正常,您应该看到JSON员工列表。

路由请求

我们来看看应用程序,看看它在做什么,首先看一下EmployeeRouter类。该类根据URL和HTTP方法将传入的HTTP请求路由到适当的处理程序。

@Configuration

public class EmployeeRouter {

@Bean

public RouterFunction route(EmployeeHandler handler) {

return RouterFunctions.route(

GET("/employees").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),

handler::getAllEmployees)

.andRoute(

GET("/employee/fn/{fn}/ln/{ln}")

.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),

handler::getEmployee)

.andRoute(

PUT("/employee").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),

handler::createNewEmployee)

.andRoute(

DELETE("/employee/id/{id}").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),

handler::deleteEmployee)

.andRoute(

GET("/departments").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),

handler::getAllDepartments);

}

}

在Spring WebFlux中,因为它是非阻塞的,所以这些处理程序必须返回一个Mono 。

处理请求

下面要看的类是处理请求的类EmployeeHandler。

@Component

public class EmployeeHandler {

private final EmployeeRepository repository;

public EmployeeHandler(EmployeeRepository repository) {

this.repository = repository;

}

public Mono getAllEmployees(ServerRequest request) {

Flux employees = repository.getAllEmployees();

return ServerResponse.ok()

.contentType(MediaType.APPLICATION_JSON)

.body(employees, Employee.class);

}

public Mono getEmployee(ServerRequest request) {

String firstName = request.pathVariable("fn");

String lastName = request.pathVariable("ln");

Mono employee = repository.getEmployee(firstName, lastName);

return ServerResponse.ok()

.contentType(MediaType.APPLICATION_JSON)

.body(employee, Employee.class);

}

public Mono createNewEmployee(ServerRequest request) {

Mono employeeMono = request.bodyToMono(Employee.class);

Mono employee = repository.createNewEmployee(employeeMono);

return ServerResponse.ok()

.contentType(MediaType.APPLICATION_JSON)

.body(employee, Employee.class);

}

public Mono deleteEmployee(ServerRequest request) {

String id = request.pathVariable("id");

Mono employee = repository.deleteEmployee(id);

return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).build(employee);

}

public Mono getAllDepartments(ServerRequest request) {

Flux allDepartments = repository.getAllDepartments();

return ServerResponse.ok()

.contentType(MediaType.APPLICATION_JSON)

.body(allDepartments, Department.class);

}

}

这是负责处理传入请求的类。每个句柄方法返回一个Mono 。ServerResponse对象具有一个用于创建响应的构建器,并且有一些方法可以使用Fluxes和Monos进行响应,该ServerResponse对象也将自动序列化你的结果。此外,如果想返回响应流,WebFlux会自动将响应转换为JSON列表。你可以看到这个在getAllEmployees和getAllDepoartment方法中实现了。更近一点的方法是deleteEmployee方法,该deleteEmployee方法与其他方法稍有不同。您会注意到大多数方法都使用.body方法来返回响应。该deleteEmployee却没有.body方法,它使用.build方法来返回响应,这实际用来返回Mono。

见下页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值