class path resource [application.properties] cannot be opened because it does not exist深度解析

一、问题现象

当springboot采用配置文件外置,在pom.xml文件中的 build标签下添加上 resource标签,这代表着打包时候excludes内部的文件从打的jar包踢出去,如果是  yml,则改成对应的 application.yml即可

        
    			
				src\main\resources
				
					application.properties
					application-dev.properties
					application-prod.properties
					application-test.properties
				
			
		

然后就开始执行

 java -jar xxxx.jar -Dspring.config.location=application.properties

但是却意外的发现竟然报错了

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.webank.ips.App]; nested exception is java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:272)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:92)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
	at com.webank.ips.App.main(App.java:24)
Caused by: java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
	at org.springframework.core.io.support.EncodedResource.getInputStream(EncodedResource.java:154)
	at org.springframework.core.io.support.PropertiesLoaderUtils.fillProperties(PropertiesLoaderUtils.java:98)
	at org.springframework.core.io.support.PropertiesLoaderUtils.fillProperties(PropertiesLoaderUtils.java:72)
	at org.springframework.core.io.support.PropertiesLoaderUtils.loadProperties(PropertiesLoaderUtils.java:58)
	at org.springframework.core.io.support.ResourcePropertySource.(ResourcePropertySource.java:65)
	at org.springframework.core.io.support.DefaultPropertySourceFactory.createPropertySource(DefaultPropertySourceFactory.java:36)
	at org.springframework.context.annotation.ConfigurationClassParser.processPropertySource(ConfigurationClassParser.java:440)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:271)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:190)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:292)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167)
	... 13 more

 二、解决过程

这个错误竟然是 : java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist

这时候非常怀疑难道是  -Dspring.config.location 的路径写错了,于是改成绝对路径测试一下依旧报错。

 java -jar xxxx.jar -Dspring.config.location=/xxxx/xxx/application.properties

依旧行不通,于是,查看错误信息,其实错误信息就是定位错误问题的,最可怕的不是错误信息很多,而是没有错误信息,这就难以下手了。这次还不错,打印错误信息很详细。

简单介绍一些错误信息,这个是方法栈的调用关系,可以看到,每一行都是一个类的某个方法,显示的还有行号。对于排查错误问题很有用,接下来分析一下错误信息:


//这里是异常最终的提示信息   class path resource [application.properties] cannot be opened because it does not exist
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.webank.ips.App]; nested exception is java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:272)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:92)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
	at com.webank.ips.App.main(App.java:24)   

//这部分打印的错误信息时启动app之后,创建beanFactory,通过postProcessBeanxxxx来注册bean信息。

 

//举例这个Caused by 最近的一行就是错误信息的直接原因,  getInputStream  这个方法在加载resource文件失败,因为是找不到。
Caused by: java.io.FileNotFoundException: class path resource [application.properties] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
	at org.springframework.core.io.support.EncodedResource.getInputStream(EncodedResource.java:154)
	at org.springframework.core.io.support.PropertiesLoaderUtils.fillProperties(PropertiesLoaderUtils.java:98)
	at org.springframework.core.io.support.PropertiesLoaderUtils.fillProperties(PropertiesLoaderUtils.java:72)
	at org.springframework.core.io.support.PropertiesLoaderUtils.loadProperties(PropertiesLoaderUtils.java:58)
	at org.springframework.core.io.support.ResourcePropertySource.(ResourcePropertySource.java:65)
	at org.springframework.core.io.support.DefaultPropertySourceFactory.createPropertySource(DefaultPropertySourceFactory.java:36)
	at org.springframework.context.annotation.ConfigurationClassParser.processPropertySource(ConfigurationClassParser.java:440)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:271)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:190)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:292)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167)

从错误信息里面可以看出来是初始化bean的时候要加载resources文件,结果找不到,而引起的错误。看着一脸懵逼,明明是配置文件外置,为何会在bean初始化的过程中引用resources。这时候就得根据错误信息打断点。找到里错误最近的方法。

class path resource [application.properties] cannot be opened because it does not exist深度解析_第1张图片

发现打在这个地方的断点,是初始化所有在默认扫描路径下的创建的Java文件,第一个是 Application.java 这个类,正常初始化完成。接着是我创建的一个配置类,结果报错了。。

class path resource [application.properties] cannot be opened because it does not exist深度解析_第2张图片
跟到这里发现竟然要读取classptah:application.xml。 因为项目中的配置文件已经提出来了。。这肯定是获取不到了,。然后继续执行果然报错了。class path resource [application.properties] cannot be opened because it does not exist深度解析_第3张图片

这里是要加载application.properties文件的。完蛋,项目内没有,结果报错了。

然后找到初始化报错的这个类,发现了一个坑。

因为这个类中要通过@Value("${xxx}")获取配置文件的内容,于是就在这里写了这行代码,之前是没有配置文件外置,一切都是正常的。当项目改造,把配置文件外置启动了,发现了这个问题。

其实,不必要加 这行代码的,因为内容中都是类的对象方法在获取,完全可以在创建对象的时候去加在这部分内容,这时候配置文件也加载进去了,也就不会出现这个问题了。

如果使用到了类的静态方法,那么就需要将类变量的set方法上写@Value()  即可。 

 

总结:在写代码的时候一定要细心,没必要的代码不要写,要为自己写的每一行代码负责。细心,细心,再细心。

你可能感兴趣的:(spring,boot,java)