java Spring Boot YML 和 StandAlone Tomcat 8 服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32327522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:01:14  来源:igfitidea点击:

Spring Boot YML and StandAlone Tomcat 8 Server

javaspringspring-mvctomcatspring-boot

提问by Shivam Sinha

I have the following directory structure/config file:

我有以下目录结构/配置文件:

src/main/resource/config: 
application.yml 
application-dev.yml 
application-sit.yml

Note according to the "Bootiful Configuration" https://spring.io/blog/2015/01/13/configuring-it-all-out-or-12-factor-app-style-configuration-with-spring:

根据“引导配置https://spring.io/blog/2015/01/13/configuring-it-all-out-or-12-factor-app-style-configuration-with-spring 注意

Spring Boot will read the properties in src/main/resources/application.properties by default. If a profile is active, it will also automatically reads in the configuration files based on the profile name, like src/main/resources/application-foo.properties where foo is the current profile. If the Snake YML library is on the classpath, then it will also automatically load YML files.

Spring Boot 默认会读取 src/main/resources/application.properties 中的属性。如果配置文件处于活动状态,它还会根据配置文件名称自动读入配置文件,例如 src/main/resources/application-foo.properties,其中 foo 是当前配置文件。如果 Snake YML 库在类路径上,那么它也会自动加载 YML 文件。

Since snake YML jar is in class path if I set --spring.profiles.active=devas a program arg in eclipse run configuration and use this as my main method Ever thing works as expected:

由于蛇 YML jar 在类路径中,如果我--spring.profiles.active=dev在 eclipse 运行配置中设置为程序 arg 并将其用作我的主要方法,任何事情都按预期工作:

  public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);

        SimpleCommandLinePropertySource source = new SimpleCommandLinePropertySource(args);

        // Check if the selected profile has been set as argument.
        // if not the development profile will be added
        addDefaultProfile(app, source);

        app.run(args);
    }

    /**
     * Set a default profile if it has not been set
     */
    private static void addDefaultProfile(SpringApplication app, SimpleCommandLinePropertySource source) {
        if (!source.containsProperty("spring.profiles.active")) {
            app.setAdditionalProfiles(Constants.SPRING_PROFILE_DEVELOPMENT);
        }
    }

(Please note the main method reference above is from the following class used in my code: https://github.com/jarias/generator-jhipster-ember/blob/master/app/templates/src/main/java/package/_Application.java)

(请注意上面的主要方法引用来自我的代码中使用的以下类:https: //github.com/jarias/generator-jhipster-ember/blob/master/app/templates/src/main/java/package/ _Application.java)

Everything works as expected for spring.profile.active=dev. Which means that both: application.yml(loaded by default) and application-dev.yml(active profile) property files are loaded and excludesapplication-sit.ymlsince sit isn't an active profile.

spring.profile.active=dev 一切正常。这意味着: application.yml(默认加载)和application-dev.yml(活动配置文件)属性文件都被加载并排除application-sit.yml,因为sat不是活动配置文件。

This embedded container works great for dev testing. However I want to release this into production by generating a war and deploy it to a standalone Tomcat8 Server.

这个嵌入式容器非常适合开发测试。但是,我想通过生成War并将其部署到独立的 Tomcat8 服务器来将其发布到生产中。

For that I created an implementation of WebApplicationInitializer which is required by Tomcat8 server to automatically detect, bootstrap and start spring application on the standalone server.

为此,我创建了一个 WebApplicationInitializer 实现,Tomcat8 服务器需要它来自动检测、引导和启动独立服务器上的 spring 应用程序。

@Configuration
public class WebAppInit implements WebApplicationInitializer {


    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
        }
}

After deploying the war I receive the following error I attempt to start the standalone server and receive the following error :

部署War后,我收到以下错误我尝试启动独立服务器并收到以下错误:

Caused by: org.springframework.beans.factory.enter code hereBeanCreationException: Could not autowire field: private java.lang.String com.titlefeed.config.db.DbConfigJPA.databaseUrl; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder spring.data.postgres.uri' in string value "${spring.data.postgres.uri}"

引起:org.springframework.beans.factory.enter code hereBeanCreationException:无法自动装配字段:private java.lang.String com.titlefeed.config.db.DbConfigJPA.databaseUrl; 嵌套异常是 java.lang.IllegalArgumentException:无法解析字符串值“${spring.data.postgres.uri}”中的占位符 spring.data.postgres.uri'

Which implies the Tomcat Server/Spring isntloading the application-dev.yml since that contains the properties: spring.data.postgres.uri

这意味着Tomcat服务器/春心不是加载,因为该应用dev.yml包含属性:spring.data.postgres.uri

So I attempted the following two solutions

所以我尝试了以下两种解决方案

  1. added -Dspring.profiles.active=devto JAVA_OPTS in tomcat/bin/catalina.sh
  2. added spring.profiles.active=devto tomcat/conf/catalina.properties
  1. 添加-Dspring.profiles.active=dev到 tomcat/bin/catalina.sh 中的 JAVA_OPTS
  2. 添加spring.profiles.active=dev到 tomcat/conf/catalina.properties

And neither of them worked. How can I get the standalone tomcat server to load the yml file associated with the spring.profiles.active property.

他们都没有工作。如何让独立的 tomcat 服务器加载与 spring.profiles.active 属性关联的 yml 文件。

It works fine for the embedded springboot server started from eclipse but doesnt for an standalong server ?

它适用于从 Eclipse 启动的嵌入式 springboot 服务器,但不适用于独立服务器?

EDIT1: M. Deinum- Implemented your suggested solution below however still got the following error:

EDIT1:M. Deinum- 在下面实施了您建议的解决方案,但仍然出现以下错误:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.data.postgres.uri' in string value "${spring.data.postgres.uri}

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.data.postgres.uri' in string value "${spring.data.postgres.uri}

It seems like the -Dspring.profiles.active=dev isn't getting set.

似乎 -Dspring.profiles.active=dev 没有设置。

@Configuration
public class WebAppInit extends SpringBootServletInitializer {

 @Override

    protected WebApplicationContext createRootApplicationContext(
            ServletContext servletContext) {
           log.info("Properly INITALIZE spring CONTEXT");
           ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
           servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
           return super.createRootApplicationContext(servletContext);
    }

}

EDIT 2 ACV:- Adding "--spring.profiles.active=dev" as apart of JAVA_OPTS variable in the startup script: tomcat/bin/catalina.sh is not a viable option

编辑 2 ACV:- 在启动脚本中添加“--spring.profiles.active=dev”作为 JAVA_OPTS 变量的一部分:tomcat/bin/catalina.sh 不是一个可行的选项

E.g:

例如:

 JAVA_OPTS="$JAVA_OPTS --spring.profiles.active=dev ...etc

Gives the following error:

给出以下错误:

Unrecognized option: --spring.profiles.active=dev Error: Could not create the Java Virtual Machine."

无法识别的选项:--spring.profiles.active=dev 错误:无法创建 Java 虚拟机。”

EDIT 3:Amended application.ymlto include the following property

编辑 3:修改application.yml以包含以下属性

spring:
  profiles:
    active: dev

Redeployed the war. Went to the exploded tomcat directory location to ensure the property was present webapps/feedserver/WEB-INF/classes/config/application.yml

重新部署War。转到爆炸的 tomcat 目录位置以确保该属性存在webapps/feedserver/WEB-INF/classes/config/application.yml

And the issue still occurred.

而且问题还是出现了。

EDIT 4:Added application.properties under the tomcat exploded webdir: webapps/feedserver/WEB-INF/classes/application.properties:

编辑4:在tomcat爆炸的webdir下添加application.properties:webapps/feedserver/WEB-INF/classes/application.properties:

spring.profiles.active=dev
spring.data.postgres.uri=jdbc:postgresql://localhost:5432/feedserver

restarted tomcat and the issue still occurred.

重启tomcat,问题依旧。

Its seems like its not picking up either application.propertiesor application.yml

它似乎没有选择application.propertiesapplication.yml

EDIT 5Used the recommended way to start the spring boot server for an external container:

编辑 5使用推荐的方式为外部容器启动 spring boot 服务器:

@Configuration
public class WebAppInit extends SpringBootServletInitializer {

 @Override
 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
     return application.sources(Application.class);
 }

}

Edit 6:

编辑6:

I added -Dspring.profiles.active=devto the start command args:

我将-Dspring.profiles.active=dev添加到启动命令参数中:

/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/bin/java -Djava.util.logging.config.file=/Users/shivamsinha/Desktop/Programming/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dlog4j.rootLevel=ERROR -Dlog4j.rootAppender=console -DENV=dev -Dlog4j.configuration=/WEB-INF/classes/properties/log4j.properties -DTOMCAT_DIR=WEB-INF/classes/ -Djava.endorsed.dirs=/Users/shivamsinha/Desktop/Programming/tomcat/endorsed -classpath /Users/shivamsinha/Desktop/Programming/tomcat/bin/bootstrap.jar:/Users/shivamsinha/Desktop/Programming/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/Users/shivamsinha/Desktop/Programming/tomcat -Dcatalina.home=/Users/shivamsinha/Desktop/Programming/tomcat -Djava.io.tmpdir=/Users/shivamsinha/Desktop/Programming/tomcat/temp org.apache.catalina.startup.Bootstrap -Dspring.profiles.active=dev start

However I stil get the following exception in the logs:

但是我仍然在日志中收到以下异常:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.titlefeed.config.db.DbConfigJPA.databaseUrl; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.data.postgres.uri' in string value "${spring.data.postgres.uri}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 68 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.data.postgres.uri' in string value "${spring.data.postgres.uri}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:801)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:955)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 70 more

02-Sep-2015 03:15:40.472 SEVERE [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive /Users/shivamsinha/Desktop/Programming/tomcat/webapps/feedserver-1.0.0.war
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/feedserver-1.0.0]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:728)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:917)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1701)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

采纳答案by Shivam Sinha

Credit: @M. Deinum

信用:@M。迪努姆

There are two options for passing spring profile args into Tomcat 8.

将 spring 配置文件参数传递到 Tomcat 8 有两种选择。

1.Set it as environment variable

1.设置为环境变量

Tomcat allows you to set environment config in CATALINA_HOME/setenv.shor CATALINA_BASE/setenv.shthat are called during the start process.

Tomcat 允许您在启动过程中设置CATALINA_HOME/setenv.shCATALINA_BASE/setenv.sh调用的环境配置。

setenv.sh:
export SPRING_PROFILES_ACTIVE=dev

You might also want to create a src/main/resources/banner.txtwith this line in it:

您可能还想src/main/resources/banner.txt用这一行创建一个:

active profiles     :: ${spring.profiles.active}

It won't work in your IDE (it reads from your jar/war's MANIFEST.MF file, which you won't have if you're compiling normally), but it's REALLY handy in the environments you care about -- everything BUT your local environment!

它在您的 IDE 中不起作用(它从您的 jar/war 的 MANIFEST.MF 文件中读取,如果您正常编译,您将不会拥有该文件),但它在您关心的环境中非常方便——除了您的所有内容当地环境!

2.Add it to the start script/command before the before the executing class

2.将它添加到执行类之前的启动脚本/命令中

I modified CATALINA_HOME/catalina.shadded a declared variable:

我修改CATALINA_HOME/catalina.sh添加了一个声明的变量:

SPRING_PROFILE="dev"

SPRING_PROFILE="dev"

And at all the relevant executions added it to script:

并且在所有相关执行中将其添加到脚本中:

  eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      -Dspring.profiles.active="\"$SPRING_PROFILE\"" \
      org.apache.catalina.startup.Bootstrap "$@" start \
      >> "$CATALINA_OUT" 2>&1 "&"

Obviously this isn't the recommended approach. But it works! If you do have the exact replicable steps for doing it the recommend approach feel free to post the answer and if it works i'll accept it.

显然,这不是推荐的方法。但它有效!如果您确实有确切的可复制步骤,推荐的方法可以随意发布答案,如果可行,我会接受。

回答by Jimmy Fencer

I came across this when looking for a solution for passing spring profile to a standalone tomcat server. In case anybody has the same issue, what worked for me was adding the property to tomcat catalina.properties - one line: spring.profiles.active=dev

我在寻找将 spring 配置文件传递给独立 tomcat 服务器的解决方案时遇到了这个问题。如果有人遇到同样的问题,对我有用的是将属性添加到 tomcat catalina.properties - 一行:spring.profiles.active=dev

回答by Dimitri Hautot

Try with removing the "config" subfolder from the config path. Shouldn't all the configuration files live in src/main/resources?

尝试从配置路径中删除“config”子文件夹。不是所有的配置文件都应该存在src/main/resources吗?