将Spring启动/云与Amazon AWS一起使用lambda不会注入值

min*_*das 14 java spring spring-boot spring-cloud aws-lambda

我有一个AWS lambda RequestHandler类,由AWS直接调用.最终我需要使用Spring Boot,因为我需要它能够从Spring Cloud配置服务器检索数据.

问题是如果我从我自己的开发环境本地运行代码但是在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
Run Code Online (Sandbox Code Playgroud)

我试过了什么:

  • 使用常规的Spring MVC,但这并没有与@Valueinjection/Spring云集成.
  • 使用@PropertySource- 但发现它不支持.yml文件
  • 验证以确保配置服务器正在为任何IP地址提供请求(没有IP地址过滤)
  • 运行curl以确保价值被带回
  • 验证确保.jar实际上包含bootstrap.ymljar根
  • 验证以确保.jar实际上包含Spring Boot类.FWIW我正在使用Maven shade插件,它将项目打包成一个包含所有依赖项的胖.jar.

注意:AWS Lambda 支持环境变量,因此我不能设置任何类似的东西spring.application.name(既不是环境变量也不是-D参数).我也无法控制实际启动的基础类MyClass- 这对最终用户完全透明.我只是打包jar并提供入口点(类名),休息得到照顾.

有什么我可以错过的吗?我能以更好的方式调试这个吗?

Rob*_*ily 22

经过一些调试后,我确定问题在于使用Maven Shade插件.Spring Boot在其autoconfigure jar中查找META-INF/spring.factories jar,请参阅此处获取有关此内容的一些信息.为了正确打包Spring Boot jar,您需要使用Spring Boot Maven插件并将其设置为在maven重新打包阶段运行.它在本地IDE中工作的原因是因为您没有运行Shade打包的jar.他们在插件中做了一些特别的魔术,让事情在Shade插件不知道的地方找到了.

我能够创建一些最初没有注入值的示例代码,但现在我使用了正确的插件.看到这个GitHub回购,看看我做了什么.

我没有将它与Spring Cloud连接,但现在Spring Boot注入的其余部分正在运行,我认为它应该是直截了当的.

正如我在评论中提到的,您可能只想考虑一个简单的REST调用来获取云配置并自己注入,以节省在每次请求时加载Spring应用程序的开销.

更新:对于Spring Boot 1.4.x,您必须在Spring Boot插件中提供此配置:

            <configuration>
                <layout>MODULE</layout>
            </configuration>
Run Code Online (Sandbox Code Playgroud)

如果你没有,那么默认情况下插件的新行为是将所有jar放在BOOT-INF下,因为jar的目的是可执行并让bootstrap进程加载它.我在解决这里遇到的情况警告时发现了这一点.有关参考,请参阅https://github.com/spring-projects/spring-boot/issues/5465.