[英]EnableBinding, Output, Input deprecated Since version of 3.1 of Spring Cloud Stream
Since version 3.1 the major API for working with queues is deprecated.从 3.1 版开始,主要的 API 用于处理队列已被弃用。 In the class comment it says:
在 class 评论中它说:
Deprecated as of 3.1 in favor of functional programming model
自 3.1 起弃用,支持函数式编程 model
I searched a lot in the web for a solution but didn't find a solid E2E explanation on how I should migrate.我在 web 中搜索了很多解决方案,但没有找到关于我应该如何迁移的可靠的 E2E 解释。
Looking for examples for:寻找以下示例:
If there are a few ways to do that (as I saw in web) I'd be glad for an explanation and the typical use case for each option as well.如果有几种方法可以做到这一点(正如我在网上看到的那样),我很高兴得到解释以及每个选项的典型用例。
First, some references which may help:首先,一些可能有帮助的参考资料:
TL;DR TL;博士
Instead of working with annotation-based configuration, spring now uses detected beans of Consumer
/ Function
/ Supplier
to define your streams for you. spring 现在不再使用基于注释的配置,而是使用检测到的
Consumer
/ Function
/ Supplier
bean 为您定义流。
Input/Consumer输入/消费者
Whereas before you had code looking like this:而在您的代码看起来像这样之前:
interface BindableGradesChannel {
@Input
fun gradesChannel(): SubscribableChannel
companion object {
const val INPUT = "gradesChannel"
}
}
and the usage was similar to:用法类似于:
@Service
@EnableBinding(BindableGradesChannel::class)
class GradesListener {
private val log = LoggerFactory.getLogger(GradesListener::class.java)
@StreamListener(BindableScoresChannel.INPUT)
fun listen(grade: Grade) {
log.info("Received $grade")
// do something
}
}
now the entire definition is irrelevant, and can be done like so:现在整个定义是无关紧要的,可以这样做:
@Service
class GradesListener {
private val log = LoggerFactory.getLogger(GradesListener::class.java)
@Bean
fun gradesChannel(): Consumer<Grade> {
return Consumer { listen(grade = it) }
}
fun listen(grade: Grade) {
log.info("Received $grade")
// do something
}
}
notice how the Consumer
bean replaced the @StreamListener
and the @Input
.注意
Consumer
bean 是如何替换了@StreamListener
和@Input
的。
Regarding the configuration, if before in order to configure you had an application.yml
looking like so:关于配置,如果之前为了配置你有一个
application.yml
看起来像这样:
spring:
cloud:
stream:
bindings:
gradesChannel:
destination: GradesExchange
group: grades-updates
consumer:
concurrency: 10
max-attempts: 3
now it should be like so:现在应该是这样的:
spring:
cloud:
stream:
bindings:
gradesChannel-in-0:
destination: GradesExchange
group: grades-updates
consumer:
concurrency: 10
max-attempts: 3
notice how gradesChannel
was replaced by gradesChannel-in-0
- to understand the full naming convention please see the naming convention link at the top.请注意
gradesChannel
是如何被gradesChannel-in-0
替换的——要了解完整的命名约定,请查看顶部的命名约定链接。
Some details:一些细节:
spring.cloud.function.definition
property.spring.cloud.function.definition
属性。gradesChannel
you can set spring.cloud.stream.function.bindings.gradesChannel-in-0=gradesChannel
and use everywhere in the configuration gradesChannel
. gradesChannel
you can set spring.cloud.stream.function.bindings.gradesChannel-in-0=gradesChannel
and use everywhere in the configuration gradesChannel
. Output/Supplier输出/供应商
The concept here is similar, you replace config and code looking like this:这里的概念是相似的,你替换配置和代码看起来像这样:
interface BindableStudentsChannel {
@Output
fun studentsChannel(): MessageChannel
}
and和
@Service
@EnableBinding(BindableStudentsChannel::class)
class StudentsQueueWriter(private val studentsChannel: BindableStudentsChannel) {
fun publish(message: Message<Student>) {
studentsChannel.studentsChannel().send(message)
}
}
can now be replaced by:现在可以替换为:
@Service
class StudentsQueueWriter {
@Bean
fun studentsChannel(): Supplier<Student> {
return Supplier { Student("Adam") }
}
}
As you can see, we have a major difference - when is it called and by who?如您所见,我们有一个主要区别 - 它何时以及由谁调用?
Before we could trigger it manually, but now it is triggered by spring, every second (by default).之前我们可以手动触发它,但现在它由 spring 触发,每秒触发一次(默认情况下)。 This is fine for use cases such as when you need to publish a sensor data every second, but this is not good when you want to send the message on an event.
这对于用例来说很好,例如当您需要每秒发布传感器数据时,但是当您想要在事件上发送消息时这并不好。 Besides using
Function
for whatever reason, spring offers 2 alternatives:除了出于任何原因使用
Function
之外,spring 还提供 2 种选择:
StreamBridge - link StreamBridge - 链接
Using StreamBridge
you can.使用
StreamBridge
可以。 define the target explicitly like so:像这样明确定义目标:
@Service
class StudentsQueueWriter(private val streamBridge: StreamBridge) {
fun publish(message: Message<Student>) {
streamBridge.send("studentsChannel-out-0", message)
}
}
This way you don't define the target channel as a bean, but you can still send the message.这样您就不会将目标通道定义为 bean,但您仍然可以发送消息。 The downside is that you have some explicit configuration in your class.
缺点是您在 class 中有一些明确的配置。
Reactor API - link反应堆 API - 链接
The other way is to use some kind of reactive mechanism such as EmitterProcessor
, and to return it.另一种方法是使用某种反应机制,例如
EmitterProcessor
,并返回它。 Using this your code will look similar to:使用它,您的代码将类似于:
@Service
class StudentsQueueWriter {
val students: EmitterProcessor<Student> = EmitterProcessor.create()
@Bean
fun studentsChannel(): Supplier<Flux<Student>> {
return Supplier { students }
}
}
and the usage may be similar to:用法可能类似于:
class MyClass(val studentsQueueWriter: StudentsQueueWriter) {
fun newStudent() {
studentsQueueWriter.students.onNext(Student("Adam"))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.