将 Spring boot/cloud 与 Amazon AWS lambda 一起使用不会注入值
Using Spring boot/cloud with Amazon AWS lambda does not inject values
我有一个由 AWS 直接调用的 AWS lambda RequestHandler
class。最终我需要让它与 Spring Boot 一起工作,因为我需要它能够从 Spring 云配置服务器检索数据。
问题是代码 如果我 运行 在本地 来自我自己的开发环境但 在部署时无法注入配置值AWS.
@Configuration
@EnableAutoConfiguration
@ComponentScan("my.package")
public class MyClass implements com.amazonaws.services.lambda.runtime.RequestHandler<I, O> {
public O handleRequest(I input, Context context) {
ApplicationContext applicationContext = new SpringApplicationBuilder()
.main(getClass())
.showBanner(false)
.web(false)
.sources(getClass())
.addCommandLineProperties(false)
.build()
.run();
log.info(applicationContext.getBean(SomeConfigClass.class).foo);
// prints cloud-injected value when running from local dev env
//
// prints "${path.to.value}" literal when running from AWS
// even though Spring Boot starts successfully without errors
}
}
@Configuration
public class SomeConfigClass {
@Value("${path.to.value}")
public String foo;
}
src/main/resources/bootstrap.yml:
spring:
application:
name: my_service
cloud:
config:
uri: http://my.server
failFast: true
profile: localdev
我尝试了什么:
- 使用常规 Spring MVC,但是这个 doesn't have integration with
@Value
injection/Spring cloud.
- 使用
@PropertySource
- 但发现它不支持 .yml 文件
- 已验证以确保配置服务器正在为任何 IP 地址的请求提供服务(没有 IP 地址过滤)
- 运行宁
curl
确保值被带回
- 已验证以确保 .jar 实际上包含
bootstrap.yml
在 jar root
- 已验证以确保 .jar 实际包含 Spring Boot classes。 FWIW 我正在使用 Maven shade 插件,它将项目打包成一个包含所有依赖项的 fat .jar。
注意:AWS Lambda 不 支持环境变量,因此我不能设置任何类似 spring.application.name
的东西(既不是环境变量也不是 -D
参数).我也无法控制实际启动 MyClass
的底层 classes - 这对最终用户来说是完全透明的。我只是打包 jar 并提供入口点(class 名称),剩下的就处理好了。
有什么我可能错过的吗?有什么办法可以更好地调试它吗?
经过一些调试后,我确定问题出在使用 Maven Shade 插件上。 Spring Boot 在其自动配置 jar 中查找 META-INF/spring.factories jar see here for some information on this. In order to package a Spring Boot jar correctly you need to use the Spring Boot Maven Plugin 并在 maven 重新打包阶段将其设置为 运行。它在您的本地 IDE 工作的原因是因为您没有 运行 安装 Shade 打包的 jar。他们在他们的插件中做了一些特殊的魔术,以将 Shade 插件不知道的东西放在正确的位置。
我能够创建一些示例代码,这些代码最初没有注入值,但现在可以使用,因为我使用了正确的插件。请参阅 this GitHub repo 查看我所做的工作。
我没有将它与 Spring Cloud 连接,但现在 Spring 启动注入的其余部分正在工作,我认为它应该很简单。
正如我在评论中提到的,您可能只想考虑一个简单的 REST 调用来获取云配置并自行注入,以节省每个请求都加载 Spring 应用程序的开销。
更新:对于 Spring 启动 1。4.x 您必须在 Spring 启动插件中提供此配置:
<configuration>
<layout>MODULE</layout>
</configuration>
如果你不这样做,那么默认情况下,插件的新行为是将所有 jar 放在 BOOT-INF 下,因为目的是让 jar 可执行并让 bootstrap 进程加载它.我在解决为此处遇到的情况添加警告时发现了这一点。请参阅 https://github.com/spring-projects/spring-boot/issues/5465 以供参考。
我有一个由 AWS 直接调用的 AWS lambda RequestHandler
class。最终我需要让它与 Spring Boot 一起工作,因为我需要它能够从 Spring 云配置服务器检索数据。
问题是代码 如果我 运行 在本地 来自我自己的开发环境但 在部署时无法注入配置值AWS.
@Configuration
@EnableAutoConfiguration
@ComponentScan("my.package")
public class MyClass implements com.amazonaws.services.lambda.runtime.RequestHandler<I, O> {
public O handleRequest(I input, Context context) {
ApplicationContext applicationContext = new SpringApplicationBuilder()
.main(getClass())
.showBanner(false)
.web(false)
.sources(getClass())
.addCommandLineProperties(false)
.build()
.run();
log.info(applicationContext.getBean(SomeConfigClass.class).foo);
// prints cloud-injected value when running from local dev env
//
// prints "${path.to.value}" literal when running from AWS
// even though Spring Boot starts successfully without errors
}
}
@Configuration
public class SomeConfigClass {
@Value("${path.to.value}")
public String foo;
}
src/main/resources/bootstrap.yml:
spring:
application:
name: my_service
cloud:
config:
uri: http://my.server
failFast: true
profile: localdev
我尝试了什么:
- 使用常规 Spring MVC,但是这个 doesn't have integration with
@Value
injection/Spring cloud. - 使用
@PropertySource
- 但发现它不支持 .yml 文件 - 已验证以确保配置服务器正在为任何 IP 地址的请求提供服务(没有 IP 地址过滤)
- 运行宁
curl
确保值被带回 - 已验证以确保 .jar 实际上包含
bootstrap.yml
在 jar root - 已验证以确保 .jar 实际包含 Spring Boot classes。 FWIW 我正在使用 Maven shade 插件,它将项目打包成一个包含所有依赖项的 fat .jar。
注意:AWS Lambda 不 支持环境变量,因此我不能设置任何类似 spring.application.name
的东西(既不是环境变量也不是 -D
参数).我也无法控制实际启动 MyClass
的底层 classes - 这对最终用户来说是完全透明的。我只是打包 jar 并提供入口点(class 名称),剩下的就处理好了。
有什么我可能错过的吗?有什么办法可以更好地调试它吗?
经过一些调试后,我确定问题出在使用 Maven Shade 插件上。 Spring Boot 在其自动配置 jar 中查找 META-INF/spring.factories jar see here for some information on this. In order to package a Spring Boot jar correctly you need to use the Spring Boot Maven Plugin 并在 maven 重新打包阶段将其设置为 运行。它在您的本地 IDE 工作的原因是因为您没有 运行 安装 Shade 打包的 jar。他们在他们的插件中做了一些特殊的魔术,以将 Shade 插件不知道的东西放在正确的位置。
我能够创建一些示例代码,这些代码最初没有注入值,但现在可以使用,因为我使用了正确的插件。请参阅 this GitHub repo 查看我所做的工作。
我没有将它与 Spring Cloud 连接,但现在 Spring 启动注入的其余部分正在工作,我认为它应该很简单。
正如我在评论中提到的,您可能只想考虑一个简单的 REST 调用来获取云配置并自行注入,以节省每个请求都加载 Spring 应用程序的开销。
更新:对于 Spring 启动 1。4.x 您必须在 Spring 启动插件中提供此配置:
<configuration>
<layout>MODULE</layout>
</configuration>
如果你不这样做,那么默认情况下,插件的新行为是将所有 jar 放在 BOOT-INF 下,因为目的是让 jar 可执行并让 bootstrap 进程加载它.我在解决为此处遇到的情况添加警告时发现了这一点。请参阅 https://github.com/spring-projects/spring-boot/issues/5465 以供参考。