前言
此篇重点是SpringBoot自动装配Liquibase时,如何实现把changelog文件外置到jar包外
问题
spring.liquibase.change-log 是changlog的位置,但是他默认位置是LiquibaseProperties类中属性changeLog的默认值"classpath:/db/changelog/db.changelog-master.yaml",一般配置也只能从classpath:出发读jar包内的路径,
如果你直接配了包外的位置,不带classpath,会报错如下:
2022-10-09 11:05:10.859 WARN 22524 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: The file master.xml was not found in
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/classes!/
**省略中间**
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/lib/spring-tx-5.3.23.jar!/
Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.
2022-10-09 11:05:10.871 INFO 22524 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-10-09 11:05:10.885 ERROR 22524 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: The file master.xml was not found in
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/classes!/
**省略中间**
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/lib/spring-tx-5.3.23.jar!/
Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.23.jar!/:5.3.23]
**省略中间**
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [liquibase-tool.jar:0.0.1]
Caused by: liquibase.exception.ChangeLogParseException: The file master.xml was not found in
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/classes!/
**省略中间**
- jar:file:/D:/GitAll/liquibase-tool/target/liquibase-tool-/liquibase-tool.jar!/BOOT-INF/lib/spring-tx-5.3.23.jar!/
Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parseToNode(XMLChangeLogSAXParser.java:99) ~[liquibase-core-4.9.1.jar!/:na]
**省略中间**
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.23.jar!/:5.3.23]
... 23 common frames omitted
关键信息就是这些,意思是现在只支持包里的相对路径,不支持绝对路径,就算把liquibase版本从4降成3也会报错,还没4报的详细
Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: The file master.xml was not found in ***
Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.
外置changelog
修改文件加载器
找到源码中这个类,把类复制到自己liquibase项目里修改,以后启动的时候加载的就是自定义的类了
liquibase.integration.spring.SpringLiquibase 找到createLiquibase方法
原方法:
protected Liquibase createLiquibase(Connection c) throws LiquibaseException {
SpringResourceAccessor resourceAccessor = this.createResourceOpener();
Liquibase liquibase = new Liquibase(this.getChangeLog(), resourceAccessor, this.createDatabase(c, resourceAccessor));
**省略**
改成:
protected Liquibase createLiquibase(Connection c) throws LiquibaseException {
ResourceAccessor resourceAccessor = new FileSystemResourceAccessor(System.getProperty("user.dir"));
Liquibase liquibase = new Liquibase(this.getChangeLog(), resourceAccessor, this.createDatabase(c, resourceAccessor));
**省略**
什么意思,我把文件系统定位到我jar包位置,然后我把配置文件放这就行,比如使用assembly把资源文件外置到jar同级目录再打成tar或zip包
SpringBoot配置文件设置相对路径
spring.liquibase.change-log=master.xml
change-log配置相对路径
关键是属性relativeToChangelogFile设为true,意思是我不去resource下面找了,我根据主配置文件master的位置,设置相对路径找changelog
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<include file="changelog/test.xml" author="oxye" relativeToChangelogFile="true"/>
</databaseChangeLog>
启动验证
必须成功,纯纯的科技与狠活啊