开发博客系统的时候有一个需求,就是希望系统启动时,自动将指定文件夹中的md文件写入到数据库,这样我每更新一篇文章只需将文章拷贝入那个文件夹即可。(当然也可以开发界面上传的方式,但我不想搞得那么复杂,怎么方便怎么来)。数据库表长这样:
存储文章的文件夹长这样:
这里用@PostConstruct这个注解很好实现,注意系统启动时,初始化的顺序为:构造方法 -> @Autowired -> @PostConstruct
@Component
@Order(Ordered.HIGHEST_PRECEDENCE) //指定执行顺序
public class InitHandler {
@Value("${file.upload.abpath}") //从配置文件中取出指定文件夹
private String abpath;
@Autowired
private ArticleService articleService; //引入ArticleService接口操作数据库
private Logger logger = LoggerFactory.getLogger(this.getClass()); //定义logger写日志
public InitHandler(){
this.logger.info("开始数据初始化");
}
@PostConstruct
public void init() throws Exception {
this.logger.info("数据库 初始化开始");
//1.读取abpath中所有的文件
//需要过滤的文件夹,存放image
String imgAbPath=abpath+"assets/";
//需要过滤的文件夹,测试
String testPath=abpath+"test/";
ArrayList<String> ar=new ArrayList<>();
ar.add(imgAbPath);
ar.add(testPath);
//获取所有文件路径列表
ArrayList<String> fs = FileUtil.getDirsOrFiles(abpath, ar);
List<Article> articles = articleService.queryAll();
//获取数据库中所有md文件title,用一个List接收
List<String> list=new ArrayList<>();
articles.forEach(article -> {
list.add(article.getTitle());
});
for(String s :fs){
File f=new File(s);
//获取绝对路径
this.logger.info("originalName: "+f.getAbsolutePath());
String arabpath =f.getAbsolutePath();
//获取名子
String name=f.getName().split("\\.")[0];
//过滤掉数据库中已有md文件,这种方法快,不用重复查数据库,提高效率
if(list.contains(name)){
continue;
}
//将数据写入数据库
Article art=new Article();
art.setCategoryId(1L);
art.setName(f.getName());
art.setTitle(name);
art.setCreateTime(new Timestamp(System.currentTimeMillis()));
articleService.addArticle(art);
this.logger.info(f.getName()+"已写入数据库");
}
}
}
这里用到的getDirsOrFiles(String strPath,ArrayList filterDirs)定义如下:
/**
*
* @param strPath 文件夹的绝对路径
* @param filterDirs 文件夹中需要过滤掉的文件夹List
* @return 递归查询到的文体绝对路径列表
* @throws Exception
*/
public static ArrayList<String> getDirsOrFiles(String strPath,ArrayList<String> filterDirs) throws Exception {
ArrayList<String> mfiles = new ArrayList<String>();
try {
File f = new File(strPath);
if (f.isDirectory()) {
File[] fList = f.listFiles();
for (int j = 0; j < fList.length; j++) {
if (fList[j].isDirectory()) {
//如果含有filterDirs中包含的文件夹则过滤掉
for(String s:filterDirs){
if (fList[j].equals(filterDirs)){
continue;
}
}
// System.out.println("Directory is: " + fList[j].getPath());
getDirsOrFiles(fList[j].getPath(),filterDirs); // 对当前目录下仍是目录的路径进行遍历
}
}
for (int j = 0; j < fList.length; j++) {
if (fList[j].isFile()) {
String name = fList[j].getPath().toString();
// System.out.println("Filename is: " + name);
mfiles.add(fList[j].getPath());
}
}
}
return mfiles;
} catch (Exception e) {
System.err.println("Error: " + e);
return null;
}
}
这个函数的作用是递归获取某文件夹下所有文件,同时可以指定在递归过程中过滤掉指定的文件夹,比如指定文件夹中的assets文件夹是放图片的,我不需要获取里面的png或jpg文件,于是可以将其过滤掉。
启动系统可以看到日志如下 :
说明系统启动时成功执行初始化数据库的操作。