Spring Boot中使用RSocket

栏目: Java · 发布时间: 7年前

内容简介:让我们从添加这个依赖会传递性的拉取

RSocket 应用层协议支持 Reactive Streams 语义, 例如:用RSocket作为HTTP的一种替代方案。在本教程中, 我们将看到 RSocket 用在spring boot中,特别是spring boot 如何帮助抽象出更低级别的RSocket API。

2. 依赖

让我们从添加 spring-boot-starter-rsocket 依赖开始:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-rsocket</artifactId>
</dependency>
复制代码

这个依赖会传递性的拉取 RSocket 相关的依赖,比如: rsocket-corersocket-transport-netty

3.示例的应用程序

现在继续我们的简单应用程序。为了突出 RSocket 提供的交互模式,我打算创建一个交易应用程序, 交易应用程序包括客户端和服务器。

3.1. 服务器设置

首先,我们设置由springboot应用程序引导的 RSocket server 服务器。 因为有 spring-boot-starter-rsocket dependency 依赖,所以springboot会自动配置 RSocket server 。 跟平常一样, 可以用属性驱动的方式修改 RSocket server 默认配置值。例如:通过增加如下配置在 application.properties 中,来修改 RSocket 端口

spring.rsocket.server.port=7000
复制代码

也可以根据需要进一步修改服务器的其他属性

3.2.设置客户端

接下来,我们来设置客户端,也是一个springboot应用程序。虽然springboot自动配置大部分RSocket相关的组件,但还要自定义一些对象来完成设置。

@Configuration
public class ClientConfiguration {

    @Bean
    public RSocket rSocket() {
        return RSocketFactory
          .connect()
          .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE)
          .frameDecoder(PayloadDecoder.ZERO_COPY)
          .transport(TcpClientTransport.create(7000))
          .start()
          .block();
    }

    @Bean
    RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) {
        return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies);
    }
}
复制代码

这儿我们正在创建 RSocket 客户端并且配置TCP端口为:7000。注意: 该服务端口我们在前面已经配置过。 接下来我们定义了一个RSocket的装饰器对象 RSocketRequester 。 这个对象在我们跟 RSocket server 交互时会为我们提供帮助。 定义这些对象配置后,我们还只是有了一个骨架。在接下来,我们将暴露不同的交互模式, 并看看springboot在这个地方提供帮助的。

4. springboot RSocket 中的 Request/Response

我们从 Request/Response 开始, HTTP 也使用这种通信方式,这也是最常见的、最相似的交互模式。 在这种交互模式里, 由客户端初始化通信并发送一个请求。之后,服务器端执行操作并返回一个响应给客户端--这时通信完成。 在我们的交易应用程序里, 一个客户端询问一个给定的股票的当前的市场数据。 作为回复,服务器会传递请求的数据。

4.1.服务器

在服务器这边,我们首先应该创建一个 controller 来持有我们的处理器方法。 我们会使用 @MessageMapping 注解来代替像SpringMVC中的 @RequestMapping 或者 @GetMapping 注解

@Controller
public class MarketDataRSocketController {

    private final MarketDataRepository marketDataRepository;

    public MarketDataRSocketController(MarketDataRepository marketDataRepository) {
        this.marketDataRepository = marketDataRepository;
    }

    @MessageMapping("currentMarketData")
    public Mono<MarketData> currentMarketData(MarketDataRequest marketDataRequest) {
        return marketDataRepository.getOne(marketDataRequest.getStock());
    }
}
复制代码

来研究下我们的控制器。 我们将使用 @Controller 注解来定义一个控制器来处理进入RSocket的请求。 另外,注解 @MessageMapping 让我们定义我们感兴趣的路由和如何响应一个请求。 在这个示例中, 服务器监听路由 currentMarketData , 并响应一个单一的结果 Mono<MarketData> 给客户端。

4.2. 客户端

接下来, 我们的RSocket客户端应该询问一只股票的价格并得到一个单一的响应。 为了初始化请求, 我们该使用 RSocketRequester 类,如下:

@RestController
public class MarketDataRestController {

    private final RSocketRequester rSocketRequester;

    public MarketDataRestController(RSocketRequester rSocketRequester) {
        this.rSocketRequester = rSocketRequester;
    }

    @GetMapping(value = "/current/{stock}")
    public Publisher<MarketData> current(@PathVariable("stock") String stock) {
        return rSocketRequester
          .route("currentMarketData")
          .data(new MarketDataRequest(stock))
          .retrieveMono(MarketData.class);
    }
}
复制代码

注意:在示例中, RSocket 客户端也是一个 REST 风格的 controller ,以此来访问我们的 RSocket 服务器。因此,我们使用 @RestController@GetMapping 注解来定义我们的请求/响应端点。 在端点方法中, 我们使用的是类 RSocketRequester 并指定了路由。 事实上,这个是服务器端 RSocket 所期望的路由,然后我们传递请求数据。最后,当调用 retrieveMono() 方法时,springboot会帮我们初始化一个请求/响应交互。

5. Spring Boot RSocket 中的 Fire And Forget 模式

接下来我们将查看 Fire And Forget 交互模式。正如名字提示的一样,客户端发送一个请求给服务器,但是不期望服务器的返回响应回来。 在我们的交易程序中, 一些客户端会作为数据资源服务,并且推送市场数据给服务器端。

5.1.服务器端

我们来创建另外一个端点在我们的服务器应用程序中,如下:

@MessageMapping("collectMarketData")
public Mono<Void> collectMarketData(MarketData marketData) {
    marketDataRepository.add(marketData);
    return Mono.empty();
}
复制代码

我们又一次定义了一个新的 @MessageMapping 路由为 collectMarketData 。此外, Spring Boot自动转换传入的负载为一个 MarketData 实例。 但是,这儿最大的不同是我们返回一个 Mono<Void> ,因为客户端不需要服务器的返回。

5.2. 客户端

来看看我们如何初始化我们的 fire-and-forget 模式的请求。 我们将创建另外一个REST风格的端点,如下:

@GetMapping(value = "/collect")
public Publisher<Void> collect() {
    return rSocketRequester
      .route("collectMarketData")
      .data(getMarketData())
      .send();
}
复制代码

这儿我们指定路由和负载将是一个 MarketData 实例。 由于我们使用 send() 方法来代替 retrieveMono() ,所有交互模式变成了 fire-and-forget 模式。

6. Spring Boot RSocket 中的 Request Stream

请求流是一种更复杂的交互模式, 这个模式中客户端发送一个请求,但是在一段时间内从服务器端获取到多个响应。 为了模拟这种交互模式, 客户端会询问给定股票的所有市场数据。

6.1.服务器端

我们从服务器端开始。 我们将添加另外一个消息映射方法,如下:

@MessageMapping("feedMarketData")
public Flux<MarketData> feedMarketData(MarketDataRequest marketDataRequest) {
    return marketDataRepository.getAll(marketDataRequest.getStock());
}
复制代码

正如所见, 这个处理器方法跟其他的处理器方法非常类似。 不同的部分是我们返回一个 Flux<MarketData> 来代替 Mono<MarketData> 。 最后我们的RSocket服务器会返回多个响应给客户端。

6.2.客户端

在客户端这边, 我们该创建一个端点来初始化请求/响应通信,如下:

@GetMapping(value = "/feed/{stock}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Publisher<MarketData> feed(@PathVariable("stock") String stock) {
    return rSocketRequester
      .route("feedMarketData")
      .data(new MarketDataRequest(stock))
      .retrieveFlux(MarketData.class);
}
复制代码

我们来研究下RSocket请求。 首先我们定义了路由和请求负载。 然后,我们定义了使用 retrieveFlux() 调用的响应期望。这部分决定了交互模式。 另外注意:由于我们的客户端也是 REST 风格的服务器,客户端也定义了响应媒介类型 MediaType.TEXT_EVENT_STREAM_VALUE

7.异常的处理

现在让我们看看在服务器程序中,如何以声明式的方式处理异常。 当处理请求/响应式, 我可以简单的使用 @MessageExceptionHandler 注解,如下:

@MessageExceptionHandler
public Mono<MarketData> handleException(Exception e) {
    return Mono.just(MarketData.fromException(e));
}
复制代码

这里我们给异常处理方法标记注解为 @MessageExceptionHandler 。作为结果, 这个方法将处理所有类型的异常, 因为 Exception 是所有其他类型的异常的超类。 我们也可以明确地创建更多的不同类型的,不同的异常处理方法。 这当然是请求/响应模式,并且我们返回的是 Mono<MarketData> 。我们期望这里的响应类型跟我们的交互模式的返回类型相匹配。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming in Haskell

Programming in Haskell

Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99

Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具