如何将Spring Boot application.properties外部化到tomcat / lib文件夹

时间:2015-06-24 03:24:58

标签: java tomcat spring-boot maven-3

我需要一个免配置,可部署的战争,myapp1.war可以从tomcat / lib文件夹中检索配置文件。 由于我有其他Web应用程序共存于同一个Tomcat:myapp2.war,myapp3.war,我需要这个布局:

tomcat/lib/myapp1/application.properties
tomcat/lib/myapp2/application.properties
tomcat/lib/myapp3/application.properties

通过这种方式,我可以在战争中构建没有任何属性文件的war文件,并在任何服务器上部署。

我已阅读Spring documentation但它解释了如何在以jar形式运行时设置位置:

java -jar myapp.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

我无法弄清楚如何在多个共存战争文件的情况下这样做。

我想知道这是否可行,还是应该放弃Spring Boot并回到传统的Spring MVC应用程序。

3 个答案:

答案 0 :(得分:30)

解决方案可能是将application- {profile} .properties加载为@ question建议的@PropertySource注释,但随后日志系统无法正常工作,如documentation所示。< / p>

  

日志记录系统在应用程序生命周期的早期初始化   并且因为在属性文件中找不到这样的日志记录属性   通过@PropertySource注释加载。

这意味着您在application- {profiles} .properties中的日志记录属性如:

logging.config=classpath:myapp1/logback.xml
logging.path = /path/to/logs
logging.file = myapp1.log

将被忽略,日志系统无法正常工作。

为了解决这个问题,我在配置应用程序时使用SpringApplicationBuilder.properties()方法在开头加载属性。在那里我设置了'spring.config.location&#39; Spring Boot使用它来加载所有application- {profiles} .properties:

public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder
                .sources(Application.class)
                .properties(getProperties());
    }

    public static void main(String[] args) {

        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
                .sources(Application.class)
                .properties(getProperties())
                .run(args);
    }

   static Properties getProperties() {
      Properties props = new Properties();
      props.put("spring.config.location", "classpath:myapp1/");
      return props;
   }
}

然后我将属性文件从src / main / resources移动到src / main / resources / myapp1

.
├src
| └main
|   └resources
|     └myapp1
|       └application.properties
|       └application-development.properties
|       └logback.xml
└─pom.xml

在pom.xml中,我必须将嵌入式tomcat库的范围设置为&#34;提供&#34;。 此外,从最终的战争中排除src / main / resources / myapp1中的所有属性文件,并生成一个免费配置的可配置战争:

    <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <failOnMissingWebXml>false</failOnMissingWebXml>
            <packagingExcludes>
              **/myapp1/
            </packagingExcludes>
        </configuration>
    </plugin>

然后在Tomcat我有

├apache-tomcat-7.0.59
 └lib
   ├─myapp1
   |  └application.properties        
   |  └logback.xml
   └─myapp2
     └application.properties
     └logback.xml

现在我可以生成配置免费战争并将其放入apache-tomcat-7.0.59 / webapps文件夹中。将使用类路径解析属性文件,每个webapp都独立:

   apache-tomcat-7.0.59/lib/myapp1
   apache-tomcat-7.0.59/lib/myapp2
   apache-tomcat-7.0.59/lib/myapp3

答案 1 :(得分:2)

使用Spring 4.2和@Annotation配置以及linux服务器上的tomcat

在您的Application类中,设置@PropertySource:

@Configuration
@EnableWebMvc
@PropertySource(value = { "classpath:application-yourapp.properties"})
@ComponentScan(basePackages = "com.yourapp")
public class YourAppWebConfiguration extends WebMvcConfigurerAdapter {

    ...
}

现在您只需要在类路径中包含属性文件

在制作中

在tomcat上部署.war文件(或任何内容),并将您的application-youpp.properties放在生产机器上。 (例如/opt/applyconfigfolder/application-yourapp.properties")

然后在你的tomcat(这里是tomcat 7)中打开bin\catalina.sh

你有这一行

# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=

只需添加包含application.properties

的文件夹的路径即可
CLASSPATH=:/opt/applyconfigfolder

如果您已经定义了一些类路径,则可以添加它

CLASSPATH=:/opt/applyconfigfolder:/yourpath1:/yourpath2:

我没有尝试使用Windows,但我认为没有问题

在Dev(使用eclipse)

├src
| └main
|   └ ....
└config
| └application-yourapp.properties

而不是src/main/resources/application-yourapp.properties

现在在eclipse中将你的配置文件夹添加到classpath,转到&#34;运行配置&#34;您的tomcat服务器(或等效服务器)并将文件夹Config添加到用户条目

enter image description here

好吧,你的application.properties不在应用程序中,你的项目在开发环境中运行得很好。

答案 2 :(得分:1)

Daniel Mora提供了一个很好的解决方案,但是可以使用spring.config.name(https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files)来代替spring.config.location,因此您可以在同一tomcat /中为不同的Web应用程序使用不同的属性文件lib目录:

    public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder
                .sources(Application.class)
                .properties(getProperties());
    }
    public static void main(String[] args) {

        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
                .sources(Application.class)
                .properties(getProperties())
                .run(args);
    }

   static Properties getProperties() {
      Properties props = new Properties();
      props.put("spring.config.name", "myapp1");
      return props;
   }
}

我认为lib目录用于第三方库,而不用于存储Web应用程序的配置属性。 因此,我认为更好的解决方案是使用conf / catalina.properties中的shared.loader属性将外部文件夹添加为其他类路径文件夹:

shared.loader = $ {catalina.base} / shared / configurations

您可以将应用程序属性app1.properties,app2.properties等保存在apache-tomcat-7.0.59 / shared / configurations中。

在找到丹尼尔·莫拉(Daniel Mora)解决方案超越SpringBootServletInitializer的configure方法之前,我的解决方案是在src / main / webapp / META-INF中添加context.xml,内容如下:

<Context>
    <Environment name="spring.config.name" value="myapp1" type="java.lang.String" override="false" description="define the property file for srping boot application"/>
</Context>