起因
同事之前维护的项目模块启动不起来了。报错如下:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
我帮助解决,也好久没有仔细看过Spring项目了,借此机会再温习一下局部。
经过
这种情况一看就是spring没有读取到url,那么思路就是以下两种
1、确实没有配置
2、配置文件未被读取到
经过查看配置以及是个老项目来判断,第一种情况直接排除。
顺着配置文件未被框架解析到这个思路走,debug进DataSourceProperties,判断确实未读取到相关配置值。
至于为什么没读取到配置文件,就要知道为什么会读取到配置,这个理论放在反思里边说。
先说解决问题思路,正常情况下什么都不配置的时候,SpringBoot项目是会读取到resources目录下的application文件的。那么可以断定,同事一定是配置了什么不可告人的配置,让资源文件没读取到,可能是配置了新的读取目录,也可能是移动了资源文件。
移动资源文件这个配置我可太熟了,jar包资源分离时就会用到。闻着味我就去看了pom下的build,发现了这个配置
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.directory}/resources</targetPath>
</resource>
</resources>
这个配置含义是:src/main/resources 目录下的资源文件会被复制到构建目录的resources子目录中。${project.build.directory} 是Maven构建目录的占位符,默认是target目录。因此,资源文件会被复制到target/resources目录中。构建出来的结构是这样的
而框架读取时识别不到这个目录下的配置(默认位置看反思中的总结),这下就了然了。
删除配置,测试,正常执行一气呵成。
如果需要构建jar包依赖分离的项目,在此基础上再指定项目读取路径即可。
反思
这次解决问题过程中我顺便温习了一下框架从哪读取配置文件资源以及如何读的知识点。
在SpringBoot2中查看ConfigFileApplicationListener类中内部类Loader的load方法,里边是可以看到扫描的路径以及资源名称。默认的路径以及前缀如下:
具体代码以及加载流程就不再赘述,关注getSearchNames()和getSearchLocations()基本就清楚了。
现在我们常用SpringBoot3+jdk17,为了防止以后会遇到类似的问题,我也顺着看了一下,发现版本升级,这代码是有所变化的,经过debug大法,和这部分相关的处理都在ConfigData相关的类里,比如ConfigDataEnvironmentPostProcessor和ConfigDataEnvironment里边,具体不再赘述,混个眼熟先。