Springboot应用启动后自动将jar包中的文件复制到指定位置,例如:springboot在项目启动时,拷贝一份application.yml文件到jar包外指定位置
分两种情况:
1.填充普通bean属性之后但在初始化之前拷贝
2.加载bean之前进行拷贝
情况1:填充普通bean属性之后但在初始化之前拷贝
-
需求
我们都知道采用Springboot有一个方便的地方,所有的依赖和静态文件,配置文件等最后都可以打成一个jar文件。在本项目中,为了方便用户的使用,配置文件默认的application.yml,现在需要读取这个文件,保存到指定的位置,这样后期可以对外边的jar包进行修改,而覆盖默认的 -
解决办法
由于是在jar文件中,因为常规的读取办法是读取不到该文件的。所以,在用IDE开发时能正常复制,打成 jar包就无法成功。采用ServletContextAware Springboot启动后自动运行
采用类加载器来读取resources目录下的文件
采用字节流读取复制到指定文件 -
代码
文件存放位置如图:
@Component
public class TestStarted implements ServletContextAware {
/**
* 复制application.ymls文件到项目外的路径cms.yml。
* 仅当该文件不存在时复制。
* 在填充普通bean属性之后但在初始化之前调用
* 类似于initializingbean的afterpropertiesset或自定义init方法的回调
*/
@Override
public void setServletContext(ServletContext servletContext) {
try {
File dbFile = new File("D:\\project\\other-project\\cms\\adc-cms\\repository\\cms-application.yml");
if (!dbFile.exists()) {
//读取的关键步骤
InputStream fis = this.getClass().getClassLoader().getResourceAsStream("application.yml");
//创建目录
File db = new File("D:\\project\\other-project\\cms\\adc-cms\\repository\\cms-application.yml");
if (!db.exists()) {
db.getParentFile().mkdirs();
}
dbFile.createNewFile();
FileOutputStream fos = new FileOutputStream("D:\\project\\other-project\\cms\\adc-cms\\repository\\cms-application.yml");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
// System.setProperty("spring.config.location","D:\\project\\other-project\\cms\\adc-cms\\repository\\cms-application.yml");
fis.close();
fos.close();
}
//System.setProperty("spring.config.location","D:\\project\\other-project\\cms\\adc-cms\\repository\\cms-application.yml");
} catch (Exception e) {
e.printStackTrace();
}
}
}
情况2.加载bean之前进行拷贝
在启动类中,直接创建文件
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
//判断文件是否存在,不存在则创建
createFile();
SpringApplication.run(Application.class, args);
}
private static void createFile() {
InputStream fis = null;
OutputStream fos = null;
try {
File dbFile = new File("./config/application.yml");
if (!dbFile.exists()) {
dbFile.getParentFile().mkdirs();
dbFile.createNewFile();
ClassPathResource resource = new ClassPathResource("application.yml");
fis = resource.getInputStream();
fos = new FileOutputStream("./config/application.yml");
List<String> lines = IOUtils.readLines(fis);
for(String line : lines){
line = line+"\r\n";
byte[] bytes = line.getBytes();
fos.write(bytes);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(fis != null) {
fis.close();
}
if(fos != null){
fos.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
简单复制文件的方式:
使用Files.copy 来实现
public static void copyFileNew(){
//源文件
File file = new File("src/main/resources/application.yml");
Path path = file.toPath();
try {
//创建目录
File db = new File("./config/application.yml");
if (!db.exists()) {
db.getParentFile().mkdirs();
}
Files.copy (path,new FileOutputStream (db));
} catch (IOException e) {
e.printStackTrace ();
}
}
或者
//底层和上述代码类似
public static void copyFileNew(){
Path path = Paths.get ("D://a.log");//源文件
try {
Files.copy (path,new FileOutputStream (new File ("D://b.log")));
} catch (IOException e) {
e.printStackTrace ();
}
}