spring react_使用Spring WebFlux构建React性REST API –第3部分

spring react

上一篇文章的续篇中,我们将看到一个应用程序以公开React性REST API。 在此应用程序中,我们使用了

  • 带有WebFlux的Spring Boot
  • 具有响应式支持的Cassandra的Spring数据
  • 卡桑德拉数据库

下面是应用程序的高级体系结构。

让我们看一下build.gradle文件,以查看与Spring WebFlux一起使用的依赖项。

plugins {
	id 'org.springframework.boot' version '2.2.6.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'org.smarttechie'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-cassandra-reactive'
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
	testImplementation 'io.projectreactor:reactor-test'
}

test {
	useJUnitPlatform()
}

在此应用程序中,我公开了以下提到的API。 您可以从GitHub下载源代码。

终点 URI 响应
创建产品 /产品 创建产品为Mono
所有产品 /产品 以Flux的形式返回所有产品
发售产品 / product / {id} 单核细胞增多症
更新产品 / product / {id} 将产品更新为Mono

具有上述所有端点的产品控制器代码如下。

package org.smarttechie.controller;

import org.smarttechie.model.Product;
import org.smarttechie.repository.ProductRepository;
import org.smarttechie.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;

    /**
     * This endpoint allows to create a product.
     * @param product - to create
     * @return - the created product
     */
    @PostMapping("/product")
    @ResponseStatus(HttpStatus.CREATED)
    public Mono<Product> createProduct(@RequestBody Product product){
        return productService.save(product);
    }

    /**
     * This endpoint gives all the products
     * @return - the list of products available
     */
    @GetMapping("/products")
    public Flux<Product> getAllProducts(){
        return productService.getAllProducts();
    }

    /**
     * This endpoint allows to delete a product
     * @param id - to delete
     * @return
     */
    @DeleteMapping("/product/{id}")
    public Mono<Void> deleteProduct(@PathVariable int id){
        return productService.deleteProduct(id);
    }

    /**
     * This endpoint allows to update a product
     * @param product - to update
     * @return - the updated product
     */
    @PutMapping("product/{id}")
    public Mono<ResponseEntity<Product>> updateProduct(@RequestBody Product product){
        return productService.update(product);
    }
}

在构建React式API时,我们可以使用功能样式编程模型来构建API,而无需使用RestController。 在这种情况下,我们需要具有一个路由器和一个处理程序组件,如下所示。

package org.smarttechie.router;

import org.smarttechie.handler.ProductHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
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 static org.springframework.web.reactive.function.server.RequestPredicates.*;
@Configuration
public class ProductRouter {

    /**
     * The router configuration for the product handler.
     * @param productHandler
     * @return
     */
    @Bean
    public RouterFunction<ServerResponse> productsRoute(ProductHandler productHandler){

        return RouterFunctions
                .route(GET("/products").and(accept(MediaType.APPLICATION_JSON))
                        ,productHandler::getAllProducts)
                .andRoute(POST("/product").and(accept(MediaType.APPLICATION_JSON))
                        ,productHandler::createProduct)
                .andRoute(DELETE("/product/{id}").and(accept(MediaType.APPLICATION_JSON))
                        ,productHandler::deleteProduct)
                .andRoute(PUT("/product/{id}").and(accept(MediaType.APPLICATION_JSON))
                        ,productHandler::updateProduct);
    }
}
package org.smarttechie.handler;

import org.smarttechie.model.Product;
import org.smarttechie.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
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.Mono;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;

@Component
public class ProductHandler {
    @Autowired
    private ProductService productService;
    static Mono<ServerResponse> notFound = ServerResponse.notFound().build();

    /**
     * The handler to get all the available products.
     * @param serverRequest
     * @return - all the products info as part of ServerResponse
     */
    public Mono<ServerResponse> getAllProducts(ServerRequest serverRequest) {

        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(productService.getAllProducts(), Product.class);

    }

    /**
     * The handler to create a product
     * @param serverRequest
     * @return - return the created product as part of ServerResponse
     */
    public Mono<ServerResponse> createProduct(ServerRequest serverRequest) {

        Mono<Product> productToSave = serverRequest.bodyToMono(Product.class);

        return productToSave.flatMap(product ->
                ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(productService.save(product), Product.class));

    }

    /**
     * The handler to delete a product based on the product id.
     * @param serverRequest
     * @return - return the deleted product as part of ServerResponse
     */
    public Mono<ServerResponse> deleteProduct(ServerRequest serverRequest) {

        String id = serverRequest.pathVariable("id");
        Mono<Void> deleteItem = productService.deleteProduct(Integer.parseInt(id));

        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(deleteItem, Void.class);
    }

    /**
     * The handler to update a product.
     * @param serverRequest
     * @return - The updated product as part of ServerResponse
     */
    public Mono<ServerResponse> updateProduct(ServerRequest serverRequest) {
        return productService.update(serverRequest.bodyToMono(Product.class)).flatMap(product ->
                ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(fromObject(product)))
                .switchIfEmpty(notFound);
    }
}

到目前为止,我们已经看到了如何公开响应式REST API。 通过此实现,我已经使用Gatling在React式API和非React式API(使用Spring RestController构建非React式API)上做了一个简单的基准测试。 以下是React式和非React式API之间的比较指标。 这不是一个广泛的基准测试。 因此,在采用之前,请确保对您的用例进行广泛的基准测试。

GitHub上也提供了Gatling负载测试脚本,供您参考。 到此,我结束了“ 用Spring WebFlux构建响应式REST API ”系列。 我们将在另一个主题上见面。 到那时, 快乐学习!!

翻译自: https://www.javacodegeeks.com/2020/06/build-reactive-rest-apis-with-spring-webflux-part3.html

spring react

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值