天天看点

springboot - 利用@PostConstruct对自定义Bean进行初始化

开发博客系统的时候有一个需求,就是希望系统启动时,自动将指定文件夹中的md文件写入到数据库,这样我每更新一篇文章只需将文章拷贝入那个文件夹即可。(当然也可以开发界面上传的方式,但我不想搞得那么复杂,怎么方便怎么来)。数据库表长这样:

springboot - 利用@PostConstruct对自定义Bean进行初始化

存储文章的文件夹长这样:

springboot - 利用@PostConstruct对自定义Bean进行初始化

这里用@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文件,于是可以将其过滤掉。

启动系统可以看到日志如下 :

springboot - 利用@PostConstruct对自定义Bean进行初始化

说明系统启动时成功执行初始化数据库的操作。