我可以使用 @EventListener 读取 Micronauts @Singleton 类中的应用程序属性吗?

问题描述

我的 Micronaut 项目中有一个 @Singleton 类,其方法@EventListener 注释:

@Singleton
class Bot {

    @Inject
    private val environment: Environment? = null

    @EventListener
    fun initialize(event: ServerStartupEvent) {

        val key = environment?.getProperty("discord.api.key",String::class.java)?.get().orEmpty()
        
        // code that is using the key variable

    }
}

密钥在 application.yml 文件中:

discord:
  api:
    key: MY_API_KEY // key is here as it is,without " or ' quotes,tried to enclose it with quotes - it doesn't work either

但是当我尝试运行应用程序时,出现错误

java.lang.IllegalArgumentException: Invalid token,make sure you're using the token from the developer portal Bot section and not the application client secret or public key.
        at discord4j.common.util.TokenUtil.getSelfId(TokenUtil.java:35)
        at discord4j.rest.RestResources.<init>(RestResources.java:58)
        at discord4j.core.CoreResources.<init>(CoreResources.java:44)
        at discord4j.core.discordClientBuilder.lambda$create$0(discordClientBuilder.java:45)
        at discord4j.rest.RestClientBuilder.build(RestClientBuilder.java:249)
        at discord4j.core.discordClientBuilder.build(discordClientBuilder.java:85)
        at discord4j.core.discordClientBuilder.build(discordClientBuilder.java:73)
        at com.codenamite.majorbot.MajorBot.initialize(MajorBot.kt:23)
        at com.codenamite.majorbot.$MajorBotDeFinition$$exec1.invokeInternal(UnkNown Source)
        at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:151)
        at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:3414)
        at io.micronaut.aop.chain.AdapterIntroduction.intercept(AdapterIntroduction.java:81)
        at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
        at com.codenamite.majorbot.MajorBot$ApplicationEventListener$initialize1$Intercepted.onApplicationEvent(UnkNown Source)
        at io.micronaut.context.DefaultBeanContext.notifyEventListeners(DefaultBeanContext.java:1326)
        at io.micronaut.context.DefaultBeanContext.publishEvent(DefaultBeanContext.java:1311)
        at io.micronaut.http.server.netty.NettyHttpServer.fireStartupEvents(NettyHttpServer.java:512)
        at io.micronaut.http.server.netty.NettyHttpServer.start(NettyHttpServer.java:355)
        at io.micronaut.http.server.netty.NettyHttpServer.start(NettyHttpServer.java:114)
        at io.micronaut.runtime.Micronaut.lambda$start$2(Micronaut.java:77)
        at java.base/java.util.Optional.ifPresent(Optional.java:183)
        at io.micronaut.runtime.Micronaut.start(Micronaut.java:75)
        at com.codenamite.ApplicationKt.main(Application.kt:8)
Caused by: java.lang.NumberFormatException: For input string: ""
        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.base/java.lang.Long.parseLong(Long.java:702)
        at java.base/java.lang.Long.parseLong(Long.java:817)
        at discord4j.common.util.TokenUtil.getSelfId(TokenUtil.java:32)
        ... 22 common frames omitted

Caused by: java.lang.NumberFormatException: For input string: "" 部分告诉我密钥为空,因此使用了 .orEmpty() 部分。

我不知道发生了什么,我想到的唯一一个想法是当这段代码运行时这些属性不可用,但我不知道如何解决这个问题......或者也许还有别的吗?我的想法快用完了...

解决方法

我建议使用任一配置注入:https://docs.micronaut.io/latest/guide/index.html#valueAnnotation

@Context
class Bot(@Value("${discord.api.key}") String key) {

   init {
     // code that is using the key variable
   }
}

或者我更喜欢的配置属性 https://docs.micronaut.io/latest/guide/index.html#configurationProperties

你的机器人看起来像这样:

@ConfigurationProperties("discord")
class DiscordConfig {

    @NotBlank
    var token: String = ""

}



@Context
class Bot(config: DiscordConfig) {

   init {
     val client = DiscordClient.create(config.token)
     // code that is using the key variable
   }
}

我认为不需要使用服务器启动事件。 如果你用“上下文”注释你的“单例”,bean 在启动时被实例化,这与服务器启动事件完全相同。 使用构造函数注入确保在实例化时这些东西就在那里。

奥利