Tomcat 不读取 Spring-Boot 应用程序属性
Posted
技术标签:
【中文标题】Tomcat 不读取 Spring-Boot 应用程序属性【英文标题】:Tomcat Not reading Spring-Boot Application Properties 【发布时间】:2014-01-07 04:37:18 【问题描述】:我对 spring/java 还很陌生,并且一直在为我工作的项目检查 spring-boot。我一直在遵循指南,终于有了一个(半)工作的网络应用程序 MVC + JPA 用于数据访问。当我通过 Jar 方法部署应用程序时,一切正常:
java -jar build/libs/client.jar
但是,我们的应用程序最终将部署到 Tomcat (v7.0.40),因此我需要从项目中创建一个 war 文件。我遵循了 spring.io 网站上的converting jars to war 指南并遇到了问题。它似乎没有加载 application.properties 文件。以下是重要的代码sn-ps:
src/main/java/hello/GreetingController:
@Controller
@Configuration
public class GreetingController
@Value("$app.username")
private String username;
@RequestMapping("/greeting")
public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model)
model.addAttribute("name", name);
model.addAttribute("username", username);
return "greeting";
src/main/java/hello/Application.java
@ComponentScan
@EnableAutoConfiguration
public class Application
public static void main(String[] args)
SpringApplication.run(Application.class, args);
src/main/java/hello/HelloWebXml.java
public class HelloWebXml extends SpringBootServletInitializer
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
return application.sources(Application.class);
src/main/resources/application.properties
app.username=foo
为了完整起见,这里是 build.gradle:
buildscript
repositories
maven url "http://repo.spring.io/libs-snapshot"
mavenLocal()
dependencies
classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6")
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'war'
war
baseName = 'client'
version = '0.1.0'
repositories
mavenCentral()
maven url "http://repo.spring.io/libs-snapshot"
dependencies
compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M6")
compile("org.thymeleaf:thymeleaf-spring3:2.0.16")
testCompile("junit:junit:4.11")
task wrapper(type: Wrapper)
gradleVersion = '1.8'
我构建应用程序:
gradle clean build
在tomcat中丢掉war,然后tail out日志看看如下:
SEVERE: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]
.StandardHost[localhost].StandardContext[/client]]
...
...
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating the bean
with name 'greetingController': Injection of autowired dependencies failed; nested exception
is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.username' in string
value "$app.username"
...
...
...
正如我所说,当我通过 jar 运行它时它可以工作,但当我将它部署到 Tomcat 时它不起作用。我还查看了$TOMCAT_HOME/webapps/client/WEB-INF/classes
内部,我看到了application.properties
文件。所以我认为它应该在类路径上。我的问题是,为什么tomcat不加载它?我已经尝试过全面搜索,但似乎没有其他人遇到这个问题,所以我不确定它是否只是我配置错误的东西,还是什么。
提前致谢。
【问题讨论】:
Spring boot 默认加载application.properties
。尝试将 @PropertySource("application.properties")
添加到您的 @Configuration
类中,看看它是否真的找到它。
嘿@SotiriosDelimanolis 感谢您的回复。不幸的是,这也不起作用。当 tomcat 尝试加载战争时,我得到了 FileNotFoundException。如果需要,我可以给你更多细节,请告诉我。
对不起,应该是classpath:application.properties
再次感谢,我继续添加,但注意到编译器警告:Cannot find annotation method 'value()' in type 'Repeatable': class file for java.lang.annotation.Repeatable not found.
当我将它放入 tomcat 时,我得到:Failed to load bean class: hello.Application; nested exception is org.springframework.core.NestedIOException: Unable to collect imports; nested exception is java.lang.ClassNotFoundException: java.lang.annotation.Repeatable
@SotiriosDelimanolis @PropertySource
注解可以与 Spring Boot 应用程序一起使用,但如果它是 classpath:application.properties
则不需要声明它(并且有一些框架功能不能配置为@PropertySource
) - 不过这里不相关。
【参考方案1】:
听从这些人的建议:http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
尝试:
@PropertySources(value = @PropertySource("classpath:application.properties"))
然后为胜利而繁荣。
【讨论】:
连同上面的一些 cmets,这最终对我有用。我的问题仍然是,为什么它不首先加载属性?此外,将它添加到我的控制器文件中会给我一个编译器警告,我还没有完全弄清楚。 重复我上面的评论:这在 Spring Boot 应用程序中不是必需的。 这会导致一个相当奇怪的错误:“ClassCastException: PropertySource cannot be cast to java.util.Map” while using Spring Boot on Java 7 @MikeAdler 这个答案指的是PropertySources
,它是复数,而不是PropertySource
,它是单数
谢谢!这没关系,但你知道如何从其他模块加载application-xxx.properties
文件吗?【参考方案2】:
问题是您尝试在 @Configuration
类中使用 @Value
注释。来自@PropertySource的JavaDoc:
为了使用 PropertySource 中的属性解析
定义或 @Value 注释中的 $... 占位符,必须注册一个 PropertySourcesPlaceholderConfigurer。这在 XML 中使用 时会自动发生,但在使用 @Configuration 类时必须使用静态 @Bean 方法显式注册。
例如将以下行添加到 @Configuration
类:
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer()
return new PropertySourcesPlaceholderConfigurer();
但是,在您的示例中,更合适的方法是将 @Configuration
注释从 GreetingController
类(它不包含任何配置)移动到 Application
类。由于Application
类不包含任何@Value
注释,它应该可以在不建议添加静态PropertySourcesPlaceholderConfigurer
bean 的情况下工作。
【讨论】:
【参考方案3】:我来这里是为了寻找同样的问题。当 Spring Boot 应用程序在 tomcat 中作为战争运行时,application.properties 未加载,但在使用嵌入式 tomcat 运行时它工作正常。问题出在文件名中。我使用了 Application.properties 而不是 application.properties 。从 tomcat 运行时,它看起来是区分大小写的。把它放在这里,如果有人犯了和我一样的愚蠢错误
2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件 'file:./config/application.xml' 资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./config/application.yml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./config/application.properties”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./config/application.yaml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./application.xml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./application.yml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./application.properties”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“file:./application.yaml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“类路径:/config/application.xml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“类路径:/config/application.yml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“类路径:/config/application.properties”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“类路径:/config/application.yaml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“classpath:/application.xml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“classpath:/application.yml”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“类路径:/application.properties”资源未找到 2015-09-10 14:42:13,982 调试 o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] 跳过配置文件“classpath:/application.yaml”资源未找到
【讨论】:
我遇到了同样的问题。但是文件 Application.properties 是在 Maven 构建期间默认生成的。谢谢@janardhan,我被困了好几个小时【参考方案4】:我认为对于那些将默认命名“application.[properties,yaml,etc]”更改为例如“service.[properties,yaml,etc]”的人,可以将其添加到 build.gradle 任务中:
bootRun
systemProperties = [
'spring.config.name':'service'
]
【讨论】:
以上是关于Tomcat 不读取 Spring-Boot 应用程序属性的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat中的spring-boot应用程序战争部署,现有的spring web应用程序失败
在一个 Tomcat 上运行多个 Spring-boot 应用程序
带有tomcat和cxf-servlet的spring-boot
Tomcat需要很长时间才能识别spring-boot应用程序的启动