我想知道在SpringBoot中初始化许多RabbitMQ队列/绑定时,是否有办法减少样板代码的数量?
遵循事件驱动的方法,我的应用程序产生了大约50种类型的事件(它将在稍后被分成几个较小的应用程序,但仍然)。每个事件都以类型"主题"去交换。某些事件被其他应用程序消耗,某些事件被发送它们的同一应用程序额外消耗。
让我们考虑一下出版和自我消费的情况。
在SpringBoot中,我需要为每个事件声明:
So-6以一种或另一种形式提及“购买物品”的地方。样板代码的数量简直快把我累死了:)如果有50个事件,那么很容易出错——添加新事件时,需要记住将其添加到6个位置。
理想情况下,对于每项活动,我希望:
有办法优化吗?我考虑过自定义注释,但是RabbitListener不喜欢动态队列名称,如果我在某个util方法中声明队列和绑定,Spring引导就找不到它们的bean。也许有一种方法可以在代码中声明所有这些东西,但我相信这不是Spring的方法:)
所以我最终使用手动bean声明,并为每个bean使用1个bind()方法
@Configuration
@EnableConfigurationProperties(RabbitProperties::class)
class RabbitConfiguration(
private val properties: RabbitProperties,
private val connectionFactory: ConnectionFactory
) {
@Bean
fun admin() = RabbitAdmin(connectionFactory)
@Bean
fun exchange() = TopicExchange(properties.template.exchange)
@Bean
fun rabbitMessageConverter() = Jackson2JsonMessageConverter(
jacksonObjectMapper()
.registerModule(JavaTimeModule())
.registerModule(Jdk8Module())
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
)
@Value("\${okko.rabbit.queue-prefix}")
lateinit var queuePrefix: String
fun <T> bind(routingKey: String, listener: (T) -> Mono<Void>): SimpleMessageListenerContainer {
val queueName = "$queuePrefix.$routingKey"
val queue = Queue(queueName)
admin().declareQueue(queue)
admin().declareBinding(BindingBuilder.bind(queue).to(exchange()).with(routingKey)!!)
val container = SimpleMessageListenerContainer(connectionFactory)
container.addQueueNames(queueName)
container.setMessageListener(MessageListenerAdapter(MessageHandler(listener), rabbitMessageConverter()))
return container
}
internal class MessageHandler<T>(private val listener: (T) -> Mono<Void>) {
// NOTE: don't change name of this method, rabbit needs it
fun handleMessage(message: T) {
listener.invoke(message).subscribeOn(Schedulers.elastic()).subscribe()
}
}
}
@Service
@Configuration
class EventConsumerRabbit(
private val config: RabbitConfiguration,
private val routingKeys: RabbitEventRoutingKeyConfig
) {
@Bean
fun event1() = handle(routingKeys.event1)
@Bean
fun event2() = handle(routingKeys.event2)
...
private fun<T> handle(routingKey: String): Mono<Void> = config.bind<T>(routingKey) {
log.debug("consume rabbit event: $it")
... // handle event, return Mono<Void>
}
companion object {
private val log by logger()
}
}
@Configuration
@ConfigurationProperties("my.rabbit.routing-key.event")
class RabbitEventRoutingKeyConfig {
lateinit var event1: String
lateinit var event2: String
...
}
在我的应用程序中,我有几个模块不适合“is-a”或“has-a”关系,但仍然需要相互通信和传递数据。为了尝试松散地耦合这些模块,我实现了一个事件总线类,用于处理从“事件海报”到“事件侦听器”的消息传递。 如果类希望注册接收某些事件,它们可以实现< code>IEventListener。同样,如果需要将事件推到总线上,类可以调用< code > event bus::postEvent()。当调用
Redux 很大部分 受到 Flux 的启发,而最常见的关于 Flux 的抱怨是必须写一大堆的样板代码。在这章中,我们将考虑 Redux 如何根据个人风格,团队偏好,长期可维护性等自由决定代码的繁复程度。 Actions Actions 是用来描述在 app 中发生了什么的普通对象,并且是描述突变数据意图的唯一途径。很重要的一点是 不得不 dispatch 的 action 对象并非是一个样板代码
当编写< code>redux-thunk函数(称为thunks)时,有许多样板文件可以很容易地提取出来。例如,在我们的大多数异步API调用中,我们执行以下操作,没有任何副作用: 轻松点。虽然这至少涵盖了我们70%的请求,但我确信有一种优雅的方式可以将上述代码抽象为类似这样的代码(伪代码): 当我们需要检查状态和其他副作用时,我们可以返回到适当的thunk。尽管在大多数情况下...我们可以把它砍掉
创建一个有很多高质量图像的应用程序,我决定将图像缩小到所需的大小(这意味着如果图像比屏幕大,我会缩小它)。 我注意到,在一些设备上,如果图像被缩小,它们会变得模糊/像素化,但是在相同的设备上,对于相同的目标图像视图大小,如果图像没有缩小,它们看起来很好。 我决定进一步检查这个问题,并创建了一个小的POC应用程序来显示这个问题。 在向您展示代码之前,下面是我所说内容的演示: 很难看出区别,但是你可以
问题内容: 每个想要使用java.util.logging的类通常都需要声明一个记录器,如下所示: 如何避免使用MyClass.class.getName()样板代码? 问题答案: 我在Eclipse中设置了一个模板,因此我只需要键入声明的一部分,然后Eclipse将为我自动完成其余部分。 因此,我只需要键入,hit ,后跟和,Eclipse将为我填写其余部分,并添加导入声明。 这不会减少样板代码
问题内容: 让我们比较一下c:Hello_world.c: Hello_world.go: 都编译: 还有,这是什么? 大约1Mb的世界。你在跟我开玩笑吗?我做错了什么? (仅限Hello_go-> 893K) 问题答案: 文件较大是否有问题?我不知道Go,但是我认为它会静态链接某些运行时库,而C程序则不是这种情况。但是,只要程序变大,就不必担心。 如上所述这里,静态链接Go运行时是默认的。该页面